npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zero-bits/amap

v1.6.0

Published

amap hooks map utils for React

Readme

@zero-bits/amap

企业级高精度、高拓展性的 React 高德地图 (AMap) 组件库。

基于 @amap/amap-jsapi-loader 与 React Hooks 构建,专注于解决复杂大屏业务、千万级轨迹动画渲染、以及严苛的 React 闭包性能难题。


核心特性

  • ⚡️ 极致性能:底层彻底摒弃无脑 Re-render,引入高级引用代理,规避了 instance.on/off 重复绑定的性能深渊。
  • 🛡️ 内存安全:杜绝了 React useEffect 闭包卸载陷阱,保证一切地图资源按需销毁,实现真正的零内存泄露。
  • 🧩 React Portal 挂载:Marker 完美支持复杂的 React JSX 节点渲染,状态流转浑然一体。
  • 🚀 海量轨迹渲染:深度封装 PathSimplifier 引擎,轻松应对大屏设备上的百万级流光轨迹渲染与巡航动画。
  • 📦 异步稳态:所有 Utils 与 SDK Loader 使用稳健的异步状态机,彻底消除异步时序导致的白屏、空指针异常。

安装与引入

安装使用

npm install @zero-bits/amap 或 pnpm add @zero-bits/amap 

基础使用指南

1. 基础加载与地图渲染 (Loader & AmapMap)

任何地图组件必须包裹在 Loader 与 AmapMap 内。AmapMap 采用了原生 Context 下发实例,支持随处使用。

import React from 'react';
import { Loader, AmapMap } from '@zero-bits/amap';

export default function App() {
  return (
    <Loader amapKey="你的_AMAP_KEY" securityCode="你的安全密钥">
      <AmapMap
        style={{ width: '100vw', height: '100vh' }}
        zoom={11}
        center={[116.397428, 39.90923]}
        viewMode="3D"
        mapStyle="amap://styles/dark" // 支持自定义地图样式
      >
        {/* 其他地图组件放置于此 */}
      </AmapMap>
    </Loader>
  );
}

2. 标记点 (Marker)

利用 React Portal 技术,你可以直接将任何 React 组件、甚至是包含状态的组件写在 <Marker> 里,无需拼写 HTML 字符串。

import { Marker } from '@zero-bits/amap';
import { Button } from 'antd'; // 可自由使用 UI 库组件

export default function MyMap() {
  return (
    <Marker 
      position={[116.397428, 39.90923]} 
      offset={[-20, -20]}
      onClick={(e) => console.log('Marker被点击', e)}
    >
      <div className="custom-marker-node">
        <div className="pulse-dot" />
        <span>北京总部</span>
        <Button size="small">查看详情</Button>
      </div>
    </Marker>
  )
}

3. 高性能轨迹流光动画 (PathSimplifier)

用于展示交通路网流光、车辆历史轨迹等海量点位巡航功能。

import { useRef, useEffect } from 'react';
import { PathSimplifier } from '@zero-bits/amap';

const trajectoryData = [
  {
    name: "车辆 A 历史轨迹",
    path: [ [116.4, 39.9], [116.45, 39.95], [116.5, 39.9] ]
  }
];

export default function Demo() {
  const pathRef = useRef(null);

  useEffect(() => {
    // 你可以直接操作底层导航器实例,控制巡航
    pathRef.current?.start('car_1'); 
  }, []);

  return (
    <PathSimplifier
      ref={pathRef}
      data={trajectoryData}
      getPath={(d) => d.path}
      getHoverTitle={(d) => d.name}
      autoSetFitView={true}
      navigators={[
        { id: 'car_1', pathIndex: 0, loop: true, speed: 5000 }
      ]}
      renderOptions={{
        pathLineStyle: { lineWidth: 6, strokeStyle: '#1890ff' }
      }}
    />
  );
}

4. 静态图层 (TileLayer)

轻松引入高德官方内置的路况图、卫星图、路网图,支持响应式切换。

import { TileLayer } from '@zero-bits/amap';

export default function Layers() {
  return (
    <>
      {/* 卫星图 */}
      <TileLayer.Satellite zIndex={10} />

      {/* 实时路况图 */}
      <TileLayer.Traffic autoRefresh={true} interval={180} zIndex={11} />

      {/* 路网图层 */}
      <TileLayer.RoadNet zIndex={12} />
    </>
  )
}

5. 地图控件 (Control)

内置官方类型控件与完全自定义的 DOM 控件。

import { Control } from '@zero-bits/amap';

export default function Controls() {
  return (
    <>
      {/* 官方自带:地图类型切换 */}
      <Control.MapType position="RT" defaultType={1} showRoad={true} />

      {/* 自定义控件:悬浮在左下角的图例 */}
      <Control.Custom position="LB">
        <div style={{ background: '#fff', padding: 12, borderRadius: 4 }}>
          <h4>业务图例</h4>
          <ul>
            <li>🔴 故障设备</li>
            <li>🟢 正常设备</li>
          </ul>
        </div>
      </Control.Custom>
    </>
  )
}

6. 基础折线 (Trajectory)

如果你仅需要画一条静态的线而不需要强大的渲染引擎,使用基础的 Trajectory 即可。

import { Trajectory } from '@zero-bits/amap';

<Trajectory
  path={[ [116.4, 39.9], [116.45, 39.95] ]}
  options={{
    strokeColor: '#ff0000',
    strokeWeight: 8,
    strokeOpacity: 0.8
  }}
  fitView={true}
/>

7. 搜索输入框聚合 (AutoComplete)

高德自动提示搜索服务的 React 封装,传入你的原生 input 元素 ID 即可实现地点搜索。

import { AutoComplete } from '@zero-bits/amap';

export default function SearchBar() {
  return (
    <div>
      <input id="my-search-box" placeholder="请输入地点..." />
      <AutoComplete 
        input="my-search-box"
        city="全国"
        onSelect={(e) => {
          console.log('用户选择了:', e.poi.name, e.poi.location);
        }} 
      />
    </div>
  )
}

高阶工具函数 Utils

本库不仅提供了组件,还提供了健壮的异步 API 封装。无需操心高德插件是否加载完成,所有方法返回安全的 Promise:

import { search, getAddressByLngLat, districtSearch } from '@zero-bits/amap/src/utils';

async function mapToolsDemo() {
  // 1. 根据关键字进行服务搜索
  const { status, result } = await search('天安门')

  // 2. 逆地理编码(经纬度 -> 真实地址)
  const address = await getAddressByLngLat(116.39, 39.9)

  // 3. 行政区划查询 (获取省份下辖的城市、边界等)
  const boundaries = await districtSearch('北京市')
}

8. 点聚合 (MarkerCluster)

对海量点位进行自动聚合,按网格合并邻近 Marker,并支持完全自定义渲染与事件交互。

基础用法

import { MarkerCluster } from '@zero-bits/amap'

const points = [
  { lnglat: [116.397428, 39.90923], id: 1, name: '北京总部' },
  { lnglat: [116.410000, 39.920000], id: 2, name: '朝阳分部' },
  { lnglat: [116.380000, 39.900000], id: 3, name: '西城仓储' }
]

export default function Demo() {
  return (
    <MarkerCluster
      data={points}
      gridSize={80}
      onClusterClick={({ marker, data }) => {
        console.log(`聚合点包含 ${data.length} 个点位`)
      }}
      onMarkerClick={({ data }) => {
        console.log('单点信息', data[0])
      }}
    />
  )
}

自定义渲染

通过 renderMarker 自定义单个点的外观,onClusterClick 可实现点击聚合圆后缩放地图:

import { useRef } from 'react'
import { AmapMap, Loader, MarkerCluster } from '@zero-bits/amap'

const points = [/* ... */]

export default function Demo() {
  const handleZoomIn = ({ marker, data }) => {
    // 点击聚合圈,地图放大到聚合内容的视野范围
    const lnglats = data.map(d => d.lnglat)
    map.setFitView(lnglats)
  }

  const customRenderMarker = ({ marker, data }) => {
    const item = data[0]
    const el = document.createElement('div')
    el.className = 'custom-car-marker'
    el.innerHTML = `<img src="${item.iconUrl}" /><span>${item.name}</span>`
    marker.setContent(el)
    marker.setOffset([-20, -40])
  }

  return (
    <Loader amapKey="你的_AMAP_KEY" securityCode="你的安全密钥">
      <AmapMap zoom={11} center={[116.397428, 39.90923]}>
        <MarkerCluster
          data={points}
          gridSize={60}
          renderMarker={customRenderMarker}
          onClusterClick={handleZoomIn}
          onMarkerClick={({ data }) => console.log(data[0])}
        />
      </AmapMap>
    </Loader>
  )
}

通过 ref 命令式操作实例

import { useRef } from 'react'
import { MarkerCluster, MarkerClusterRef } from '@zero-bits/amap'

export default function Demo() {
  const clusterRef = useRef<MarkerClusterRef>(null)

  const handleUpdateData = (newPoints) => {
    // 直接操作底层实例刷新数据,无需卸载重建组件
    clusterRef.current?.cluster?.setData(newPoints)
  }

  return (
    <MarkerCluster
      ref={clusterRef}
      data={points}
      gridSize={80}
    />
  )
}

Props

| 属性 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | | data | 聚合点位数据 | MarkerClusterDataItem[] | [] | | gridSize | 聚合网格的像素大小 | number | 80 | | renderClusterMarker | 自定义聚合点图标的渲染回调 | (context: MarkerClusterContext) => void | - | | renderMarker | 自定义非聚合的单点图标渲染回调 | (context: MarkerClusterContext) => void | - | | onClusterClick | 聚合点被点击的回调,接收高德原生事件对象与包含的点位数组 | (e: MarkerClusterEvent, data: MarkerClusterDataItem[]) => void | - | | onMarkerClick | 单点被点击的回调,接收高德原生事件对象与对应的单点数据 | (e: MarkerClusterEvent, data: MarkerClusterDataItem) => void | - |

注意:MarkerCluster 组件主要负责管理“聚合圈”和“散落点”的展现。如果不传入对应的 render 函数,则会自动使用高德的默认样式。

Types

interface MarkerClusterDataItem {
  lnglat: [number, number]
  [key: string]: unknown  // 可携带任意业务字段
}

interface MarkerClusterContext {
  marker: unknown           // 高德原生 Marker 实例,可强转使用
  data: MarkerClusterDataItem[]
}

interface MarkerClusterEvent {
  clusterData: MarkerClusterDataItem[]
  lnglat: [number, number] | { lng: number; lat: number }
  marker: unknown
  [key: string]: unknown
}

interface MarkerClusterInstance {
  setData(data: MarkerClusterDataItem[]): void
  setGridSize(gridSize: number): void
  setMap(map: AMap.Map | null): void
}

interface MarkerClusterRef {
  cluster?: MarkerClusterInstance
}

9. 次世代超级点聚合 (SuperMarkerCluster)

基于 WebGL 和底层 KD-Tree 算法打造的极限性能聚合组件,专为十万级海量数据设计。内置了“三层防御性物理隔离”与“重绘锁”,彻底根除由高德引擎缓存引起的状态污染、1 像素地理偏移和 WebGL 纹理拉伸。

最强黑科技:一键无缝切换! 你可以直接通过 cluster={boolean} 属性瞬间切换“聚合 / 散点”形态。在散点形态下,组件依然会在底层利用 KD-Tree 提供极速的屏幕视野剔除(BBox Culling),性能吊打所有传统的 React map() 循环!

import { SuperMarkerCluster } from '@zero-bits/amap'

export default function Demo() {
  return (
    <SuperMarkerCluster
      points={vehiclePoints}          // 遵循 GeoJSON 格式的数据
      cluster={mapState.showCluster}  // 🔥 核心:一键无缝开关聚合效果!无需写 if-else!
      gridSize={80}
      zIndex={111}
      collision={false}
      renderMarker={(marker) => marker.properties}
      onMarkerClick={(_, marker) => handleMarkerClick(marker.properties.extData)} 
    />
  )
}

10. 数据驱动海量图层 (LabelsLayer)

对于完全不需要聚合的海量静态站点(如数万个基站、充电桩),千万不要在 JSX 里使用 Array.map(<LabelMarker>) 循环渲染!这会导致灾难级的 React Virtual DOM 内存爆炸。

升级后的 LabelsLayer 提供了原生级的纯数据驱动引擎,只需通过 markers 属性传入数组,组件便会绕过 React 渲染树,在底层内存瞬间将配置抛入高德 WebGL 渲染管线,性能快如闪电。

import { LabelsLayer } from '@zero-bits/amap'

export default function StaticStations() {
  return (
    <LabelsLayer 
      zIndex={110} 
      collision={false} 
      animation={true}
      markers={stationMarkers} // 直接丢入配置数组,告别 JSX 循环
      onMarkerClick={(e, marker) => console.log('点击站点', marker.extData)} 
    />
  )
}

11. 实时流光巡航聚合 (LiveMarkerCluster)

专门为解决“大规模车辆平滑移动 + 实时聚合”复杂场景设计的组件。通过 BBox Diffing 引擎复用实例,并实现平滑移动与按需聚合。

关于“缓动/蠕动”动画的关键参数说明:

  • animationDuration (平滑位移时间) 控制车辆从 A 点移动到 B 点的过程。如果业务数据是 30 秒推一次,默认的 10000(10秒)会导致车辆慢动作“蠕动”,且宏观视角下极难察觉。 👉 最佳实践:将其设为 1000 或 1500 毫秒。可以让每次数据刷新时车辆轻快、敏捷地“滑”到新位置,实现类似“手机导航”的灵动感。 (注意:仅当数据的 properties.isMoving === true 时生效,否则车辆将瞬间跳跃)。

  • animation (图斑显隐动画) 透传给底层引擎,控制车辆初次加载、或由于地图缩放产生聚合/解聚时,图标渐隐渐现(Fade-in)的视觉效果。它不参与控制点到点的行驶位移。

import { LiveMarkerCluster } from '@zero-bits/amap'

export default function LiveMap() {
  return (
    <LiveMarkerCluster 
      points={vehicleData}
      animationDuration={1500} // 设置为 1.5 秒实现轻快滑动,消除 10 秒默认带来的缓慢蠕动感
      animation={true} // 控制图标刚出现时的淡入淡出效果
      renderMarker={(marker) => marker.properties}
    />
  )
}

组件总览

| 组件 | 说明 | |---|---| | Loader | 高德 SDK 异步加载器,提供全局 Context | | AmapMap | 地图容器,所有子组件的宿主 | | Marker | 支持 JSX 的自定义标注点(React Portal 实现) | | MarkerCluster | 海量点位自动聚合(基于传统 DOM 引擎) | | SuperMarkerCluster | 🚀 次世代 WebGL 超级点聚合,十万级点位极速渲染,支持一键无缝散点切换 | | LabelsLayer | ⚡️ 纯数据驱动的海量图层,彻底剥离 React 开销,T0 级极速渲染 | | LiveMarkerCluster | 🚗 实时流光巡航聚合,专为大规模车辆平滑移动场景设计 | | Trajectory | 基础静态折线 | | PathSimplifier | 高性能轨迹流光动画与巡航引擎 | | TileLayer.Satellite | 高德官方卫星图层 | | TileLayer.TiandituSatellite | 天地图卫星图层(需传入 tk,解决海外/边境无卫星图问题) | | TileLayer.Traffic | 实时路况图层 | | TileLayer.RoadNet | 路网图层 | | Control.MapType | 地图类型切换官方控件 | | Control.Custom | 任意 JSX 自定义悬浮控件 | | AutoComplete | 高德地点搜索自动提示 |