@hzab/map-combine 0.3.0-beta → 0.3.0

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/CHANGELOG.md CHANGED
@@ -1,7 +1,9 @@
1
- # @hzab/map-combine0.3.0
1
+ # @hzab/map-combine@0.3.0
2
2
 
3
3
  fix: reactpoint 添加高德地图引擎并添加相应点线面绘制
4
4
  feat: 高德地图支持 ReactPoint
5
+ feat: 增加 loadPromise 参数,用于地图异步加载判断是否加载完成
6
+ fix: 解决 ReactPoint 点击事件无法触发的问题
5
7
 
6
8
  # @hzab/map-combine0.2.8
7
9
 
package/package.json CHANGED
@@ -1,12 +1,19 @@
1
1
  {
2
2
  "name": "@hzab/map-combine",
3
- "version": "0.3.0-beta",
3
+ "version": "0.3.0",
4
4
  "description": "地图组件",
5
5
  "main": "src",
6
6
  "scripts": {
7
7
  "dev": "npm run prepare && webpack serve -c ./config/webpack.config.js --env local",
8
8
  "build": "webpack -c ./config/webpack.config.js --env production",
9
- "publish-beta": "npm publish --beta",
9
+ "version:alpha": "npm version prerelease --preid=alpha",
10
+ "publish:alpha": "npm publish --tag alpha",
11
+ "version:beta": "npm version prerelease --preid=beta",
12
+ "publish:beta": "npm publish --tag beta",
13
+ "version:patch": "npm version patch",
14
+ "version:minior": "npm version minor",
15
+ "version:major": "npm version major",
16
+ "publish:stable": "npm publish --access public",
10
17
  "publish-patch": "npm version patch && npm publish --access public",
11
18
  "publish-minor": "npm version minor && npm publish --access public",
12
19
  "publish-major": "npm version major && npm publish --access public",
@@ -22,11 +29,11 @@
22
29
  "author": "CaiYansong",
23
30
  "license": "ISC",
24
31
  "devDependencies": {
25
- "ol": "^7.4.0",
26
32
  "@amap/amap-jsapi-loader": "^1.0.1",
27
33
  "@hzab/permissions": "0.1.1",
28
34
  "@hzab/webpack-config": "^0.2.1",
29
35
  "@turf/turf": "6.5",
36
+ "@types/amap-js-api": "^1.4.16",
30
37
  "@types/react": "^17.0.62",
31
38
  "@types/react-dom": "^17.0.20",
32
39
  "antd": "^4.14.0",
@@ -36,6 +43,7 @@
36
43
  "lil-gui": "^0.19.2",
37
44
  "mobx": "^6.7.0",
38
45
  "mobx-react": "^7.6.0",
46
+ "ol": "^7.4.0",
39
47
  "react": "^17.0.2",
40
48
  "react-dom": "^17.0.2",
41
49
  "react-router-dom": "^6.14.1",
@@ -56,5 +64,6 @@
56
64
  "**.{js,jsx,ts,tsx,css,scss,less,json,html}": [
57
65
  "prettier --write"
58
66
  ]
59
- }
67
+ },
68
+ "dependencies": {}
60
69
  }
package/src/amap/AMap.ts CHANGED
@@ -1,249 +1,300 @@
1
- import { MapCombine } from "../basic/MapCombine";
2
- import { PointOption, Point } from "../basic/Point";
3
- import { ReactPointOption, ReactPoint, drawReactPoint } from "../basic/ReactPoint";
4
- import { PolylineOption, Polyline } from "../basic/Polyline";
5
- import { PolygonOption, Polygon } from "../basic/Polygon";
6
- import { Tile3DOption, Tile3D } from "../basic/Tile3D";
7
-
8
- import AMapLoader from "./loader";
9
- import { bindEvent } from "./AMapEvent";
10
- import { drawPoint } from "./AMapPoint";
11
- import { drawPolyline } from "./AMapPolyline";
12
- import { drawPolygon } from "./AMapPolygon";
13
-
14
- export interface IAMapOption {
15
- container;
16
- url?: string | string[];
17
- center?: number[];
18
- zoom?: number;
19
- maxZoom?: number;
20
- minZoom?: number;
21
- /** 地图瓦片转换规则 GCJ02 转 WGS84 */
22
- proj?: "GCJ02->WGS84";
23
- /** 高德地图 key */
24
- key: string;
25
- /** 高德地图 securityJsCode */
26
- securityJsCode: string;
27
- /** 加载的插件列表 */
28
- plugins?: [string];
29
- }
30
-
31
- export interface IFlyToViewerOpt {
32
- /**
33
- * 立即缩放到指定位置
34
- */
35
- immediately?: boolean;
36
- /**
37
- * (Array<number> = [0,0,0,0]) 距离边框的内边距,顺序:上、下、左、右
38
- */
39
- avoid?: [number, number, number, number];
40
- }
41
-
42
- export class AMap extends MapCombine {
43
- loadPromise;
44
- viewer: any;
45
- container: HTMLDivElement;
46
- option;
47
- offset: number[];
48
- fov = 0.9272952180016121;
49
- isFromLonLat = true;
50
- LbsAMap;
51
- get cursor(): string {
52
- return this.container.style.cursor;
53
- }
54
- set cursor(val: string) {
55
- this.container.style.cursor = val;
56
- }
57
-
58
- get moveable(): boolean {
59
- return this.viewer?.getStatus()?.dragEnable;
60
- }
61
- set moveable(val: boolean) {
62
- this.viewer?.setStatus({ dragEnable: val });
63
- }
64
-
65
- get center(): number[] {
66
- return this.viewer?.getCenter();
67
- }
68
- set center(val: number[]) {
69
- this.viewer?.setCenter(val);
70
- }
71
- get zoom(): number {
72
- return this.viewer?.getZoom();
73
- }
74
- set zoom(val: number) {
75
- this.viewer?.setZoom(val);
76
- }
77
-
78
- constructor(viewer = undefined) {
79
- super();
80
- viewer && this._initParamsEvent(viewer);
81
- }
82
-
83
- private _initParamsEvent(viewer) {
84
- if (!viewer) {
85
- return;
86
- }
87
- this.viewer = viewer;
88
-
89
- this.container = this.viewer.getContainer();
90
- // this.markers = this.viewer.scene.primitives.add(new Cesium.BillboardCollection());
91
-
92
- bindEvent(this);
93
- }
94
-
95
- init(opt: IAMapOption) {
96
- this.option = opt;
97
- const {
98
- container,
99
- center = [120.2288892, 30.2349677, 0],
100
- zoom = 13,
101
- url,
102
- maxZoom,
103
- minZoom,
104
- proj,
105
- key,
106
- securityJsCode,
107
- plugins,
108
- } = opt || {};
109
-
110
- this.loadPromise = new Promise((resolve, reject) => {
111
- AMapLoader({
112
- key,
113
- securityJsCode,
114
- plugins,
115
- })
116
- .then((LbsAMap: any) => {
117
- this.LbsAMap = LbsAMap;
118
- let _urls = Array.isArray(url) ? url : [url];
119
- this.viewer = new LbsAMap.Map(container, {
120
- zoom: zoom || 14,
121
- center: center || [120.160217, 30.243861],
122
- doubleClickZoom: false,
123
- zooms: minZoom && maxZoom && [minZoom, maxZoom],
124
- layers: url
125
- ? _urls.map((it: any) => {
126
- let opt = { tileUrl: "", getTileUrl: undefined };
127
- if (typeof it === "string") {
128
- opt.tileUrl = it;
129
- } else {
130
- opt = it;
131
- }
132
- // 使用 getTileUrl 解决接口地址强制改为 https 的问题
133
- opt.getTileUrl = function (x, y, z) {
134
- return opt.tileUrl.replace("{x}", x).replace("{y}", y).replace("{z}", z);
135
- };
136
-
137
- return new LbsAMap.TileLayer(opt);
138
- })
139
- : undefined,
140
- });
141
- this.viewer.on("complete", () => {
142
- resolve(this.viewer);
143
- });
144
-
145
- this._initParamsEvent(this.viewer);
146
- return this.viewer;
147
- })
148
- .catch(reject);
149
- });
150
- this.loadPromise.then(() => {
151
- this.container.appendChild(this.htmllayer);
152
- });
153
- return this.loadPromise;
154
- }
155
-
156
- createPoint<K>(option?: Partial<PointOption<K>>): Point<K> {
157
- const e = new Point(this, option);
158
- this.loadPromise.then(() => {
159
- drawPoint(this, e);
160
- });
161
- return e;
162
- }
163
-
164
- createReactPoint<K>(option?: Partial<ReactPointOption<K>>): ReactPoint<K> {
165
- const e = new ReactPoint(this, option);
166
- this.loadPromise.then(() => {
167
- drawReactPoint(this, e);
168
- });
169
- return e;
170
- }
171
-
172
- createPolyline<K>(option?: Partial<PolylineOption<K>>): Polyline<K> {
173
- const e = new Polyline(this, option);
174
- this.loadPromise.then(() => {
175
- drawPolyline(this, e);
176
- });
177
- return e;
178
- }
179
- createPolygon<K>(option?: Partial<PolygonOption<K>>): Polygon<K> {
180
- const e = new Polygon(this, option);
181
- this.loadPromise.then(() => {
182
- drawPolygon(this, e);
183
- });
184
- return e;
185
- }
186
- createTile3D(option?: Partial<Tile3DOption>): Tile3D {
187
- throw new Error("Method not implemented.");
188
- }
189
-
190
- /**
191
- * 将高德地图 Canvas 像素坐标转换为经纬度
192
- * @param {Array} p - canvas 点位数组 [x, y]
193
- * @returns {Array} p - 经纬度数组 [lng, lat]
194
- */
195
- canvasTgeography(p: number[]) {
196
- const mapInstance = this.viewer;
197
- if (!mapInstance) {
198
- this.loadPromise.then(() => {
199
- this.canvasTgeography(p);
200
- });
201
- return [];
202
- }
203
- try {
204
- const lngLat = this.viewer.lngLatToContainer(p);
205
- return [lngLat.lng, lngLat.lat];
206
- } catch (error) {
207
- console.error("canvasPixelToLngLat 转换出错:", error);
208
- return [];
209
- }
210
- }
211
-
212
- /**
213
- * 经纬度转换为高德地图 Canvas 像素坐标
214
- * @param {Array} p - 经纬度数组 [lng, lat]
215
- * @returns {Array} Canvas 像素坐标 [x, y]
216
- */
217
- geographyTcanvas(p: number[]): number[] {
218
- const mapInstance = this.viewer;
219
- if (!mapInstance) {
220
- this.loadPromise.then(() => {
221
- this.geographyTcanvas(p);
222
- });
223
- return [];
224
- }
225
- try {
226
- const containerPixel = this.viewer.lngLatToContainer(p);
227
- return [containerPixel.x, containerPixel.y];
228
- } catch (error) {
229
- console.error("lngLatToCanvasPixel 转换出错:", error);
230
- return [];
231
- }
232
- }
233
- /**
234
- * 所有点位移动至视口,调整位置及层级
235
- * @param points
236
- * @param opt
237
- * @param {Array<number> = [0,0,0,0]} opt.avoid 距离边框的内边距,顺序:上、下、左、右
238
- */
239
- flyToViewer(points: number[][], opt: IFlyToViewerOpt = { avoid: [0, 0, 0, 0], immediately: true }): void {
240
- this.loadPromise.then(() => {
241
- this.viewer.setBounds(
242
- this.getBounds(points, { canvas: this.viewer.canvas, ...opt }),
243
- opt?.immediately,
244
- opt?.avoid,
245
- );
246
- });
247
- }
248
- flyTo() {}
249
- }
1
+ import { MapCombine } from "../basic/MapCombine";
2
+ import { PointOption, Point } from "../basic/Point";
3
+ import { ReactPointOption, ReactPoint, drawReactPoint } from "../basic/ReactPoint";
4
+ import { PolylineOption, Polyline } from "../basic/Polyline";
5
+ import { PolygonOption, Polygon } from "../basic/Polygon";
6
+ import { Tile3DOption, Tile3D } from "../basic/Tile3D";
7
+
8
+ import AMapLoader from "./loader";
9
+ import { bindEvent } from "./AMapEvent";
10
+ import { drawPoint } from "./AMapPoint";
11
+ import { drawPolyline } from "./AMapPolyline";
12
+ import { drawPolygon } from "./AMapPolygon";
13
+
14
+ export interface IAMapOption {
15
+ container: HTMLDivElement;
16
+ url?: string | string[];
17
+ center?: number[];
18
+ zoom?: number;
19
+ maxZoom?: number;
20
+ minZoom?: number;
21
+ /** 地图瓦片转换规则 GCJ02 转 WGS84 */
22
+ proj?: "GCJ02->WGS84";
23
+ /** 高德地图 key */
24
+ key: string;
25
+ /** 高德地图 securityJsCode */
26
+ securityJsCode: string;
27
+ /** 加载的插件列表 */
28
+ plugins?: [string];
29
+ /** loader 配置参数 */
30
+ loaderOpt?: Object;
31
+ /** 地图初始化 配置参数 */
32
+ mapOpt?: Object;
33
+ }
34
+
35
+ export interface IFlyToViewerOpt {
36
+ /**
37
+ * 立即缩放到指定位置
38
+ */
39
+ immediately?: boolean;
40
+ /**
41
+ * (Array<number> = [0,0,0,0]) 距离边框的内边距,顺序:上、下、左、右
42
+ */
43
+ avoid?: [number, number, number, number];
44
+ /**
45
+ * 最大缩放级别
46
+ */
47
+ maxZoom?: number;
48
+ /**
49
+ * 动画时间
50
+ */
51
+ duration?: number;
52
+ }
53
+
54
+ export class AMap extends MapCombine {
55
+ viewer: any;
56
+ container: HTMLDivElement = null;
57
+ option: any = {};
58
+ offset: number[];
59
+ fov = 0.9272952180016121;
60
+ isFromLonLat = true;
61
+ LbsAMap: any;
62
+ get cursor(): string {
63
+ return this.container.style.cursor;
64
+ }
65
+ set cursor(val: string) {
66
+ this.container.style.cursor = val;
67
+ }
68
+
69
+ get moveable(): boolean {
70
+ return this.viewer?.getStatus()?.dragEnable;
71
+ }
72
+ set moveable(val: boolean) {
73
+ this.viewer?.setStatus({ dragEnable: val });
74
+ }
75
+
76
+ get center(): number[] {
77
+ return this.viewer?.getCenter();
78
+ }
79
+ set center(val: number[]) {
80
+ this.viewer?.setCenter(val);
81
+ }
82
+ get zoom(): number {
83
+ return this.viewer?.getZoom();
84
+ }
85
+ set zoom(val: number) {
86
+ this.viewer?.setZoom(val);
87
+ }
88
+
89
+ constructor(viewer = undefined) {
90
+ super();
91
+ viewer && this._initParamsEvent(viewer);
92
+ }
93
+
94
+ private _initParamsEvent(viewer) {
95
+ if (!viewer) {
96
+ return;
97
+ }
98
+ this.viewer = viewer;
99
+
100
+ this.container = this.viewer.getContainer();
101
+ // this.markers = this.viewer.scene.primitives.add(new Cesium.BillboardCollection());
102
+
103
+ bindEvent(this);
104
+ }
105
+
106
+ init(opt: IAMapOption) {
107
+ this.option = opt;
108
+ const {
109
+ container,
110
+ center = [120.2288892, 30.2349677, 0],
111
+ zoom = 13,
112
+ url,
113
+ maxZoom,
114
+ minZoom,
115
+ proj,
116
+ key,
117
+ securityJsCode,
118
+ plugins,
119
+ } = opt || {};
120
+
121
+ this.loadPromise = new Promise((resolve, reject) => {
122
+ AMapLoader({
123
+ ...opt.loaderOpt,
124
+ key,
125
+ securityJsCode,
126
+ plugins,
127
+ })
128
+ .then((LbsAMap: any) => {
129
+ this.LbsAMap = LbsAMap;
130
+ let _urls = Array.isArray(url) ? url : [url];
131
+ this.viewer = new LbsAMap.Map(container, {
132
+ ...opt.mapOpt,
133
+ zoom: zoom || 14,
134
+ center: center || [120.160217, 30.243861],
135
+ doubleClickZoom: false,
136
+ zooms: minZoom && maxZoom && [minZoom, maxZoom],
137
+ layers: url
138
+ ? _urls.map((it: any) => {
139
+ let opt = { tileUrl: "", getTileUrl: undefined };
140
+ if (typeof it === "string") {
141
+ opt.tileUrl = it;
142
+ } else {
143
+ opt = it;
144
+ }
145
+ // 使用 getTileUrl 解决接口地址强制改为 https 的问题
146
+ opt.getTileUrl = function (x, y, z) {
147
+ return opt.tileUrl.replace("{x}", x).replace("{y}", y).replace("{z}", z);
148
+ };
149
+
150
+ return new LbsAMap.TileLayer(opt);
151
+ })
152
+ : undefined,
153
+ });
154
+ this.viewer.on("complete", () => {
155
+ resolve(this);
156
+ });
157
+
158
+ this._initParamsEvent(this.viewer);
159
+ return this;
160
+ })
161
+ .catch(reject);
162
+ });
163
+ this.loadPromise.then(() => {
164
+ this.container.appendChild(this.htmllayer);
165
+ });
166
+ return this.loadPromise;
167
+ }
168
+
169
+ createPoint<K>(option?: Partial<PointOption<K>>): Point<K> {
170
+ const e = new Point(this, option);
171
+ this.loadPromise.then(() => {
172
+ drawPoint(this, e);
173
+ });
174
+ return e;
175
+ }
176
+
177
+ createReactPoint<K>(option?: Partial<ReactPointOption<K>>): ReactPoint<K> {
178
+ const e = new ReactPoint(this, option);
179
+ this.loadPromise.then(() => {
180
+ drawReactPoint(this, e);
181
+ });
182
+ return e;
183
+ }
184
+
185
+ createPolyline<K>(option?: Partial<PolylineOption<K>>): Polyline<K> {
186
+ const e = new Polyline(this, option);
187
+ this.loadPromise.then(() => {
188
+ drawPolyline(this, e);
189
+ });
190
+ return e;
191
+ }
192
+ createPolygon<K>(option?: Partial<PolygonOption<K>>): Polygon<K> {
193
+ const e = new Polygon(this, option);
194
+ this.loadPromise.then(() => {
195
+ drawPolygon(this, e);
196
+ });
197
+ return e;
198
+ }
199
+ createTile3D(option?: Partial<Tile3DOption>): Tile3D {
200
+ throw new Error("Method not implemented.");
201
+ }
202
+
203
+ /**
204
+ * 将高德地图 Canvas 像素坐标转换为经纬度
205
+ * @param {Array} p - canvas 点位数组 [x, y]
206
+ * @returns {Array} p - 经纬度数组 [lng, lat]
207
+ */
208
+ canvasTgeography(p: number[]) {
209
+ const mapInstance = this.viewer;
210
+ if (!mapInstance) {
211
+ this.loadPromise.then(() => {
212
+ this.canvasTgeography(p);
213
+ });
214
+ return [];
215
+ }
216
+ try {
217
+ const lngLat = this.viewer.lngLatToContainer(p);
218
+ return [lngLat.lng, lngLat.lat];
219
+ } catch (error) {
220
+ console.error("canvasPixelToLngLat 转换出错:", error);
221
+ return [];
222
+ }
223
+ }
224
+
225
+ /**
226
+ * 经纬度转换为高德地图 Canvas 像素坐标
227
+ * @param {Array} p - 经纬度数组 [lng, lat]
228
+ * @returns {Array} Canvas 像素坐标 [x, y]
229
+ */
230
+ geographyTcanvas(p: number[]): number[] {
231
+ const mapInstance = this.viewer;
232
+ if (!mapInstance) {
233
+ this.loadPromise.then(() => {
234
+ this.geographyTcanvas(p);
235
+ });
236
+ return [];
237
+ }
238
+ try {
239
+ const containerPixel = this.viewer.lngLatToContainer(p);
240
+ return [containerPixel.x, containerPixel.y];
241
+ } catch (error) {
242
+ console.error("lngLatToCanvasPixel 转换出错:", error);
243
+ return [];
244
+ }
245
+ }
246
+ /**
247
+ * 所有点位移动至视口,调整位置及层级
248
+ * @param points
249
+ * @param opt
250
+ * @param {Array<number> = [0,0,0,0]} opt.avoid 距离边框的内边距,顺序:上、下、左、右
251
+ */
252
+ flyToViewer(points: number[][], opt: IFlyToViewerOpt = { avoid: [0, 0, 0, 0], immediately: true }): void {
253
+ this.loadPromise.then(() => {
254
+ const [zoom, center] = this.viewer.getFitZoomAndCenterByBounds(
255
+ this.getBounds(points, { canvas: this.viewer.canvas, ...opt }),
256
+ opt?.avoid,
257
+ opt.maxZoom,
258
+ );
259
+
260
+ this.viewer.setZoomAndCenter(zoom, center, opt?.immediately, opt?.duration);
261
+ });
262
+ }
263
+
264
+ /**
265
+ * 将点集视野调整至容器内,支持相对边距(百分比)
266
+ * @param {number[][]} points - 经纬度数组 [[lng, lat], ...]
267
+ * @param {Object} opt
268
+ * @param {number[]} opt.avoid - 相对边距 [上, 下, 左, 右],取值范围 0~1,默认 [0,0,0,0]
269
+ * @param {boolean} opt.immediately - 是否立即跳转,默认 false(带动画)
270
+ */
271
+ flyToViewerPercent(points: number[][], opt = { avoid: [0, 0, 0, 0], immediately: false }) {
272
+ if (!points?.length) return;
273
+
274
+ // 计算原始经纬度范围
275
+ let west = Infinity,
276
+ east = -Infinity,
277
+ south = Infinity,
278
+ north = -Infinity;
279
+ points.forEach(([lng, lat]) => {
280
+ west = Math.min(west, lng);
281
+ east = Math.max(east, lng);
282
+ south = Math.min(south, lat);
283
+ north = Math.max(north, lat);
284
+ });
285
+
286
+ // 应用相对边距
287
+ const [top, bottom, left, right] = opt.avoid;
288
+ const lngSpan = east - west;
289
+ const latSpan = north - south;
290
+
291
+ const bounds = this.LbsAMap.Bounds(
292
+ [west - lngSpan * left, south - latSpan * bottom],
293
+ [east + lngSpan * right, north + latSpan * top],
294
+ );
295
+
296
+ this.viewer.setBounds(bounds, opt.immediately);
297
+ }
298
+
299
+ flyTo() {}
300
+ }