@cn-map/gaode-react 0.0.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024-present Jungzl.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2024-present Jungzl.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,6 +1,307 @@
1
1
  # @cn-map/gaode-react
2
2
 
3
- 高德地图 react 组件。
3
+ 高德地图 React 组件库,基于高德地图 JavaScript API 2.0 开发。提供了一套 React 组件、Hooks 和工具,用于构建高德地图应用。
4
4
 
5
- - 仓库:https://github.com/Jungzl/amap
6
- - 许可证:MIT
5
+ ## 特性
6
+
7
+ - 🎯 **类型友好** - 组件与 Hooks 提供类型定义
8
+ - 🚀 **React 19 兼容** - 支持最新的 React 特性
9
+ - 🎨 **丰富的组件** - 覆盖地图、覆盖物、图层、控件与常用工具
10
+ - 🧩 **可与原生 API 混用** - WebService 等未封装能力可直接调用原生 `AMap.*`
11
+ - 📊 **3D 可视化** - 基于 Loca 的可视化组件
12
+ - 🛠️ **易于使用** - 简洁的 API 设计
13
+ - 📦 **按需加载** - 支持组件按需导入
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ npm install @cn-map/gaode-react
19
+ ```
20
+
21
+ ```bash
22
+ yarn add @cn-map/gaode-react
23
+ ```
24
+
25
+ ```bash
26
+ pnpm add @cn-map/gaode-react
27
+ ```
28
+
29
+ ```bash
30
+ bun add @cn-map/gaode-react
31
+ ```
32
+
33
+ TypeScript 类型见 [`@cn-map/gaode-types`](../types/README.md)。
34
+
35
+ ## 使用示例
36
+
37
+ ### 基础地图
38
+
39
+ ```tsx
40
+ import { APILoader, LoadStatus, Map, Marker, useAPIStatus } from '@cn-map/gaode-react'
41
+
42
+ const App = () => {
43
+ const status = useAPIStatus('AMap')
44
+
45
+ return (
46
+ <APILoader apiKey="YOUR_AMAP_KEY">
47
+ {status === LoadStatus.Loaded && (
48
+ <Map center={[116.397428, 39.90923]} style={{ height: '400px' }} zoom={13}>
49
+ <Marker position={[116.397428, 39.90923]} />
50
+ </Map>
51
+ )}
52
+ </APILoader>
53
+ )
54
+ }
55
+
56
+ export default App
57
+ ```
58
+
59
+ or
60
+
61
+ ```tsx
62
+ import { APILoader, LoadStatus, Map, Marker } from '@cn-map/gaode-react'
63
+
64
+ const App = () => {
65
+ return (
66
+ <APILoader apiKey="YOUR_AMAP_KEY">
67
+ {status => {
68
+ if (status.AMap === LoadStatus.Loaded) {
69
+ return (
70
+ <Map center={[116.397428, 39.90923]} style={{ height: '400px' }} zoom={13}>
71
+ <Marker position={[116.397428, 39.90923]} />
72
+ </Map>
73
+ )
74
+ }
75
+ }}
76
+ </APILoader>
77
+ )
78
+ }
79
+
80
+ export default App
81
+ ```
82
+
83
+ ### 使用 Loca 可视化
84
+
85
+ ```tsx
86
+ import { APILoader, LoadStatus, Map, useAPIStatus } from '@cn-map/gaode-react'
87
+ import { GeoJSONSource, HeatMapLayer, Loca } from '@cn-map/gaode-react/loca'
88
+
89
+ const App = () => {
90
+ const status = useAPIStatus()
91
+
92
+ return (
93
+ <APILoader apiKey={import.meta.env.VITE_AMAP_KEY} Loca={{}}>
94
+ {status.AMap === LoadStatus.Loaded && (
95
+ <Map
96
+ center={[102.618687, 31.790976]}
97
+ mapStyle="amap://styles/whitesmoke"
98
+ pitch={40}
99
+ style={{ height: '400px' }}
100
+ viewMode="3D"
101
+ zoom={4}
102
+ zooms={[4, 7]}
103
+ >
104
+ {status.Loca === LoadStatus.Loaded && (
105
+ <Loca>
106
+ <GeoJSONSource url="https://a.amap.com/Loca/static/loca-v2/demos/mock_data/traffic.json">
107
+ <HeatMapLayer<{
108
+ avg: number
109
+ city: string
110
+ index: number
111
+ lnglat: string
112
+ mom: string
113
+ prov: string
114
+ ranking: number
115
+ yoy: string
116
+ }>
117
+ opacity={1}
118
+ style={{
119
+ gradient: {
120
+ 0.1: '#2A85B8',
121
+ 0.2: '#16B0A9',
122
+ 0.3: '#29CF6F',
123
+ 0.4: '#5CE182',
124
+ 0.5: '#7DF675',
125
+ 0.6: '#FFF100',
126
+ 0.7: '#FAA53F',
127
+ 1.0: '#D04343',
128
+ },
129
+ height: 500000,
130
+ heightBezier: [0, 0.53, 0.37, 0.98],
131
+ radius: 200000,
132
+ value(index, feature) {
133
+ const value = Number.parseFloat(feature.properties.mom)
134
+ return value + 10 * Math.random()
135
+ },
136
+ unit: 'meter',
137
+ }}
138
+ visible={true}
139
+ zIndex={10}
140
+ />
141
+ </GeoJSONSource>
142
+ </Loca>
143
+ )}
144
+ </Map>
145
+ )}
146
+ </APILoader>
147
+ )
148
+ }
149
+
150
+ export default App
151
+ ```
152
+
153
+ ## 核心组件
154
+
155
+ ### API 加载器
156
+
157
+ | 导出名称 | 类型 | 描述 |
158
+ | ------------------ | ---- | ------------------------------ |
159
+ | `APILoader` | 组件 | 高德地图 JavaScript API 加载器 |
160
+ | `APILoaderOptions` | 类型 | APILoader 组件的配置选项 |
161
+ | `LoadStatus` | 枚举 | 表示加载状态的枚举值 |
162
+ | `useAPIError` | Hook | 获取 API 加载错误信息的钩子 |
163
+ | `useAPILoader` | Hook | 加载高德地图 API 的钩子 |
164
+ | `useAPIStatus` | Hook | 检查 API 加载状态的钩子 |
165
+
166
+ ### 地图组件
167
+
168
+ | 导出名称 | 类型 | 描述 |
169
+ | -------- | ---- | ------------------ |
170
+ | `Map` | 组件 | 地图容器组件 |
171
+ | `useMap` | Hook | 获取地图实例的钩子 |
172
+
173
+ ### 地图控制组件
174
+
175
+ | 导出名称 | 类型 | 描述 |
176
+ | ------------- | ---- | ---------------- |
177
+ | `ControlBar` | 组件 | 组合控件 |
178
+ | `Geolocation` | 组件 | 定位控件 |
179
+ | `HawkEye` | 组件 | 鹰眼控件 |
180
+ | `MapType` | 组件 | 地图类型切换控件 |
181
+ | `Scale` | 组件 | 比例尺控件 |
182
+ | `ToolBar` | 组件 | 工具条控件 |
183
+
184
+ ### 地图图层
185
+
186
+ | 导出名称 | 类型 | 描述 |
187
+ | ---------------------------- | ---- | ---------------- |
188
+ | `Buildings`, `BuildingLayer` | 组件 | 楼块图层 |
189
+ | `CanvasLayer` | 组件 | Canvas 图层 |
190
+ | `CustomLayer` | 组件 | 自定义图层 |
191
+ | `DistrictLayer` | 组件 | 行政区图层 |
192
+ | `Country` | 组件 | 国家图层 |
193
+ | `Province` | 组件 | 省份图层 |
194
+ | `World` | 组件 | 世界图层 |
195
+ | `GLCustomLayer` | 组件 | WebGL 自定义图层 |
196
+ | `HeatMap` | 组件 | 热力图图层 |
197
+ | `ImageLayer` | 组件 | 图片图层 |
198
+ | `IndoorMap` | 组件 | 室内地图图层 |
199
+ | `LabelsLayer` | 组件 | 标注图层 |
200
+ | `LayerGroup` | 组件 | 图层群组 |
201
+ | `Mapbox` | 组件 | Mapbox 图层 |
202
+ | `MapboxVectorTileLayer` | 组件 | MVT 图层 |
203
+ | `TileLayer` | 组件 | 切片图层 |
204
+ | `Flexible` | 组件 | 灵活切片图层 |
205
+ | `Mark` | 组件 | 白嫖标记图层 |
206
+ | `RoadNet` | 组件 | 路网图层 |
207
+ | `Satellite` | 组件 | 卫星图层 |
208
+ | `Traffic` | 组件 | 实时交通图层 |
209
+ | `WMS` | 组件 | WMS 图层 |
210
+ | `WMTS` | 组件 | WMTS 图层 |
211
+ | `VectorLayer` | 组件 | 矢量图层 |
212
+
213
+ ### 覆盖物组件
214
+
215
+ | 导出名称 | 类型 | 描述 |
216
+ | --------------- | ---- | ---------- |
217
+ | `BezierCurve` | 组件 | 贝塞尔曲线 |
218
+ | `Circle` | 组件 | 圆形 |
219
+ | `CircleMarker` | 组件 | 圆点标记 |
220
+ | `ContextMenu` | 组件 | 右键菜单 |
221
+ | `ElasticMarker` | 组件 | 灵活点标记 |
222
+ | `Ellipse` | 组件 | 椭圆 |
223
+ | `IndexCluster` | 组件 | 索引点聚合 |
224
+ | `InfoWindow` | 组件 | 信息窗体 |
225
+ | `LabelMarker` | 组件 | 标注标记 |
226
+ | `Marker` | 组件 | 点标记 |
227
+ | `MarkerCluster` | 组件 | 点聚合 |
228
+ | `MassMarks` | 组件 | 海量点 |
229
+ | `OverlayGroup` | 组件 | 覆盖物群组 |
230
+ | `Polygon` | 组件 | 多边形 |
231
+ | `Polyline` | 组件 | 折线 |
232
+ | `Rectangle` | 组件 | 矩形 |
233
+ | `Text` | 组件 | 文本标记 |
234
+
235
+ ### 工具组件
236
+
237
+ | 导出名称 | 类型 | 描述 |
238
+ | ------------------- | ---- | ---------------- |
239
+ | `BezierCurveEditor` | 组件 | 贝塞尔曲线编辑器 |
240
+ | `CircleEditor` | 组件 | 圆形编辑器 |
241
+ | `EllipseEditor` | 组件 | 椭圆编辑器 |
242
+ | `MouseTool` | 组件 | 鼠标工具 |
243
+ | `PolygonEditor` | 组件 | 多边形编辑器 |
244
+ | `PolylineEditor` | 组件 | 折线编辑器 |
245
+ | `RangingTool` | 组件 | 测距工具 |
246
+ | `RectangleEditor` | 组件 | 矩形编辑器 |
247
+
248
+ ## Loca 可视化组件
249
+
250
+ 基于 Loca 库的高级 3D 可视化组件,从 `@cn-map/gaode-react/loca` 导入::
251
+
252
+ ### Loca 容器
253
+
254
+ | 导出名称 | 类型 | 描述 |
255
+ | --------- | ---- | -------------------- |
256
+ | `Loca` | 组件 | Loca 容器组件 |
257
+ | `useLoca` | Hook | 访问 Loca 实例的钩子 |
258
+
259
+ ### Loca 图层
260
+
261
+ | 导出名称 | 类型 | 描述 |
262
+ | ---------------- | ---- | ------------ |
263
+ | `GridLayer` | 组件 | 网格图层 |
264
+ | `HeatMapLayer` | 组件 | 热力图图层 |
265
+ | `HexagonLayer` | 组件 | 蜂窝图层 |
266
+ | `IconLayer` | 组件 | 图标图层 |
267
+ | `LabelsLayer` | 组件 | 标注图层 |
268
+ | `LaserLayer` | 组件 | 激光图层 |
269
+ | `LineLayer` | 组件 | 线图层 |
270
+ | `LinkLayer` | 组件 | 连接图层 |
271
+ | `PointLayer` | 组件 | 点图层 |
272
+ | `PolygonLayer` | 组件 | 面图层 |
273
+ | `PrismLayer` | 组件 | 棱柱图层 |
274
+ | `PulseLineLayer` | 组件 | 脉冲线图层 |
275
+ | `PulseLinkLayer` | 组件 | 脉冲连接图层 |
276
+ | `ScatterLayer` | 组件 | 散点图层 |
277
+ | `ZMarkerLayer` | 组件 | Z轴标记图层 |
278
+
279
+ ### Loca 光照
280
+
281
+ | 导出名称 | 类型 | 描述 |
282
+ | ------------------ | ---- | ------ |
283
+ | `AmbientLight` | 组件 | 环境光 |
284
+ | `DirectionalLight` | 组件 | 平行光 |
285
+ | `PointLight` | 组件 | 点光源 |
286
+
287
+ ### Loca UI 组件
288
+
289
+ | 导出名称 | 类型 | 描述 |
290
+ | -------- | ---- | -------- |
291
+ | `Legend` | 组件 | 图例组件 |
292
+
293
+ ### Loca 数据源
294
+
295
+ | 导出名称 | 类型 | 描述 |
296
+ | ----------------- | ---- | ---------------- |
297
+ | `GeoBufferSource` | 组件 | GeoBuffer 数据源 |
298
+ | `GeoJSONSource` | 组件 | GeoJSON 数据源 |
299
+
300
+ ## 相关链接
301
+
302
+ - [高德地图 JavaScript API 文档](https://lbs.amap.com/api/jsapi-v2/summary)
303
+ - [Loca 可视化文档](https://lbs.amap.com/api/loca-v2/intro)
304
+
305
+ ## 许可证
306
+
307
+ [MIT](https://github.com/Jungzl/amap/blob/main/LICENSE)
@@ -0,0 +1,100 @@
1
+ import { createContext, use, useEffect, useEffectEvent, useState } from "react";
2
+ import { eventToProp, lostContextError, lowercase } from "@cn-map/gaode-shared/utils";
3
+ // src/hooks/use-event-listeners.ts
4
+ function useEventListeners(target, eventProps, eventTypes = []) {
5
+ const getHandler = useEffectEvent((eventType) => {
6
+ return eventProps[eventToProp(eventType)];
7
+ });
8
+ useEffect(() => {
9
+ const _target = typeof target === "function" ? target() : target;
10
+ if (!_target) return;
11
+ const cleanupFunctions = [];
12
+ for (const eventType of eventTypes) {
13
+ const handler = (event) => {
14
+ getHandler(eventType)?.(event);
15
+ };
16
+ _target.on(lowercase(eventType), handler);
17
+ cleanupFunctions.push(() => {
18
+ _target.off(lowercase(eventType), handler);
19
+ });
20
+ }
21
+ return () => {
22
+ cleanupFunctions.forEach((cleanup) => cleanup());
23
+ };
24
+ }, [target, eventTypes]);
25
+ }
26
+ // src/hooks/use-lazy-init.ts
27
+ function useLazyInit(init) {
28
+ const [instance] = useState(init);
29
+ return instance;
30
+ }
31
+ // src/utils/helpers.ts
32
+ /**
33
+ * Splits an object into multiple objects based on the specified keys. [solid-js `splitProps`](https://github.com/solidjs/solid/blob/62305456041c0970f628449c67bc2579af330940/packages/solid/src/server/rendering.ts#L138)
34
+ * @param props
35
+ * @param keys
36
+ */
37
+ function splitProps(props, ...keys) {
38
+ const descriptors = Object.getOwnPropertyDescriptors(props);
39
+ const split = (k) => {
40
+ const clone = {};
41
+ for (let i = 0; i < k.length; i++) {
42
+ const key = k[i];
43
+ if (descriptors[key]) {
44
+ Object.defineProperty(clone, key, descriptors[key]);
45
+ delete descriptors[key];
46
+ }
47
+ }
48
+ return clone;
49
+ };
50
+ return keys.map(split).concat(split(Reflect.ownKeys(descriptors)));
51
+ }
52
+ /**
53
+ * Type guard to check if a value is a React ref object
54
+ * @param ref The value to check
55
+ * @returns True if the value is a ref object, false otherwise
56
+ */
57
+ function isRefObject(ref) {
58
+ return ref !== null && typeof ref === "object" && Object.prototype.hasOwnProperty.call(ref, "current");
59
+ }
60
+ /**
61
+ * Resolve target from RefObject, accessor function, or direct instance.
62
+ *
63
+ * @template T The type of the target instance
64
+ * @param {Target<T>} target The target to resolve, which can be a RefObject, an accessor function, or a direct instance
65
+ * @returns The resolved instance or undefined
66
+ */
67
+ function resolveTarget(target) {
68
+ return isRefObject(target) ? target.current : typeof target === "function" ? target() : target;
69
+ }
70
+ /**
71
+ * Synchronize a property of an instance with a given value.
72
+ *
73
+ * @template T The type of the instance
74
+ * @template K The key of the property to synchronize
75
+ * @param {T} instance The instance whose property is to be synchronized
76
+ * @param {K} property The key of the property to synchronize
77
+ * @param {T[K]} value The value to set for the property
78
+ */
79
+ function syncProperty(instance, property, value) {
80
+ instance[property] = value;
81
+ }
82
+ // src/map/context.ts
83
+ const EMPTY = Symbol("No Map");
84
+ const MapContext = createContext(EMPTY);
85
+ /**
86
+ * 获取地图实例 hook
87
+ */
88
+ function useMap() {
89
+ const map = use(MapContext);
90
+ if (map === EMPTY) throw lostContextError("`AMap.Map`");
91
+ return map;
92
+ }
93
+ /**
94
+ * 获取合并props的地图实例
95
+ */
96
+ function useMapInstance(mapInProps) {
97
+ const mapInCtx = use(MapContext);
98
+ return mapInProps ?? (mapInCtx === EMPTY ? null : mapInCtx);
99
+ }
100
+ export { splitProps as a, useEventListeners as c, resolveTarget as i, useMap as n, syncProperty as o, useMapInstance as r, useLazyInit as s, MapContext as t };