@hzab/map-combine 0.1.3 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,6 +1,14 @@
1
+ # @hzab/map-combine0.2.1
2
+
3
+ feat: openLayer对除EPSG:3857和EPSG:4326的瓦片坐标系取消偏移
4
+
5
+ # @hzab/map-combine0.2.0
6
+
7
+ feat: flyToViewer 所有点位移动至视口,调整位置及层级
8
+
1
9
  # @hzab/map-combine0.1.3
2
10
 
3
- feat: 添加地图preRender事件
11
+ feat: 添加地图 preRender 事件
4
12
 
5
13
  # @hzab/map-combine@0.1.0
6
14
 
@@ -8,4 +16,5 @@ feat: BIM 模型加载;旋转、平移、缩放
8
16
  feat: 地图瓦片转 84 坐标系
9
17
 
10
18
  # @hzab/map-combine@0.0.1
11
- 组件初始化
19
+
20
+ 组件初始化
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzab/map-combine",
3
- "version": "0.1.3",
3
+ "version": "0.2.1",
4
4
  "description": "地图组件",
5
5
  "main": "src",
6
6
  "scripts": {
@@ -23,6 +23,7 @@
23
23
  "devDependencies": {
24
24
  "@hzab/permissions": "0.1.1",
25
25
  "@hzab/webpack-config": "^0.2.1",
26
+ "@turf/turf": "6.5",
26
27
  "@types/react": "^17.0.62",
27
28
  "@types/react-dom": "^17.0.20",
28
29
  "antd": "^4.14.0",
@@ -42,6 +43,7 @@
42
43
  "lib": "lib"
43
44
  },
44
45
  "peerDependencies": {
46
+ "@turf/turf": "6.5",
45
47
  "coordtransform": "^2.1.2",
46
48
  "lodash": ">=4.17.21",
47
49
  "ol": "^7.4.0",
@@ -8,11 +8,13 @@ import { ReactPoint, ReactPointOption, drawReactPoint } from "./ReactPoint";
8
8
  import { Tile3D, Tile3DOption } from "./Tile3D";
9
9
  import { type BasicBusiness, type BasicBusinessOption } from "./BasicBusiness";
10
10
 
11
+ import { getBounds } from "../utils/points-viewer";
12
+
11
13
  export abstract class MapCombine {
12
14
  /* 用于挂载html元素的根节点 */
13
15
  readonly htmllayer = document.createElement("div");
14
- readonly elements = new Map<string, MapElement>()
15
- readonly event = new MapEvent()
16
+ readonly elements = new Map<string, MapElement>();
17
+ readonly event = new MapEvent();
16
18
  readonly menu: ContextMenu;
17
19
  abstract get cursor(): string;
18
20
  abstract set cursor(val: string);
@@ -20,18 +22,18 @@ export abstract class MapCombine {
20
22
  abstract get moveable(): boolean;
21
23
  abstract set moveable(val: boolean);
22
24
 
23
- abstract get center(): number[]
24
- abstract set center(val)
25
+ abstract get center(): number[];
26
+ abstract set center(val);
25
27
 
26
- abstract get zoom(): number
27
- abstract set zoom(val)
28
+ abstract get zoom(): number;
29
+ abstract set zoom(val);
28
30
 
29
31
  bussinesses = new Map<string, BasicBusiness<BasicBusinessOption>>();
30
32
 
31
33
  /** 地图是否存在 */
32
34
  isAlive = true;
33
35
  constructor() {
34
- const { htmllayer } = this
36
+ const { htmllayer } = this;
35
37
  htmllayer.style.zIndex = "1000";
36
38
  htmllayer.style.position = "absolute";
37
39
  htmllayer.style.width = "0";
@@ -46,32 +48,39 @@ export abstract class MapCombine {
46
48
  }
47
49
 
48
50
  createReactPoint<K>(option?: Partial<ReactPointOption<K>>): ReactPoint<K> {
49
- const e = new ReactPoint(this, option)
50
- drawReactPoint(this, e)
51
- return e
51
+ const e = new ReactPoint(this, option);
52
+ drawReactPoint(this, e);
53
+ return e;
52
54
  }
53
55
 
54
-
55
56
  /**
56
57
  * 设置地图视图
57
58
  * @param option 视图参数
58
59
  * @param time 设置时间会动画形式调整视图
59
60
  */
60
- abstract createPoint<K>(option?: Partial<PointOption<K>>): Point<K>
61
+ abstract createPoint<K>(option?: Partial<PointOption<K>>): Point<K>;
62
+
63
+ abstract createPolyline<K>(option?: Partial<PolylineOption<K>>): Polyline<K>;
61
64
 
62
- abstract createPolyline<K>(option?: Partial<PolylineOption<K>>): Polyline<K>
65
+ abstract createPolygon<K>(option?: Partial<PolygonOption<K>>): Polygon<K>;
63
66
 
64
- abstract createPolygon<K>(option?: Partial<PolygonOption<K>>): Polygon<K>
67
+ abstract createTile3D(option?: Partial<Tile3DOption>): Tile3D;
65
68
 
66
- abstract createTile3D(option?: Partial<Tile3DOption>): Tile3D
69
+ abstract canvasTgeography(p: number[]): number[];
67
70
 
68
- abstract canvasTgeography(p: number[]): number[]
71
+ abstract geographyTcanvas(p: number[]): number[];
72
+
73
+ /**
74
+ * 所有点位移动至视口,调整位置及层级
75
+ * @param points
76
+ */
77
+ abstract flyToViewer(points: number[][], opt?: Object): void;
69
78
 
70
- abstract geographyTcanvas(p: number[]): number[]
79
+ getBounds = getBounds;
71
80
 
72
81
  destroy() {
73
82
  this.isAlive = false;
74
- this.htmllayer.remove()
75
- this.event.trigger('destroy')
83
+ this.htmllayer.remove();
84
+ this.event.trigger("destroy");
76
85
  }
77
- }
86
+ }
@@ -247,6 +247,25 @@ export class CesiumMap extends MapCombine {
247
247
  }
248
248
  return [res.x, res.y];
249
249
  }
250
+
251
+ /**
252
+ * 所有点位移动至视口,调整位置及层级
253
+ * @param points
254
+ * @param opt
255
+ * @param {Array<number> = [0,0,0,0]} opt.avoid 距离边框的内边距,顺序:上、下、左、右
256
+ */
257
+ flyToViewer(points, opt = { avoid: [0, 0, 0, 0] }) {
258
+ // 创建矩形
259
+ const rectangle = Cesium.Rectangle.fromDegrees(
260
+ ...this.getBounds(points, { canvas: this.viewer.scene.canvas, ...opt }),
261
+ );
262
+
263
+ // 设置相机视角
264
+ this.viewer.camera.setView({
265
+ destination: rectangle,
266
+ ...opt,
267
+ });
268
+ }
250
269
  }
251
270
 
252
271
  function createColorCanvas(color) {
@@ -1,4 +1,3 @@
1
-
2
1
  import { MapCombine } from "../basic/MapCombine";
3
2
  import { PointOption, Point } from "../basic/Point";
4
3
  import { PolygonOption, Polygon } from "../basic/Polygon";
@@ -11,15 +10,14 @@ import { drawPolyline } from "./MinePolyline";
11
10
  import { drawTile3D } from "./MineTile3D";
12
11
 
13
12
  export class MineMap extends MapCombine {
14
-
15
13
  viewer: any;
16
14
  container: HTMLDivElement;
17
15
 
18
16
  get cursor(): string {
19
- return this.viewer.getCursor()
17
+ return this.viewer.getCursor();
20
18
  }
21
19
  set cursor(val: string) {
22
- this.viewer.setCursor(val)
20
+ this.viewer.setCursor(val);
23
21
  }
24
22
 
25
23
  get moveable(): boolean {
@@ -29,31 +27,29 @@ export class MineMap extends MapCombine {
29
27
  val ? this.viewer.dragPan.enable() : this.viewer.dragPan.disable();
30
28
  }
31
29
  get center(): number[] {
32
- const p = this.viewer.getCenter()
33
- return [p.lng, p.lat]
30
+ const p = this.viewer.getCenter();
31
+ return [p.lng, p.lat];
34
32
  }
35
33
  set center(val: number[]) {
36
- this.viewer.setCenter(val)
34
+ this.viewer.setCenter(val);
37
35
  }
38
36
 
39
37
  get zoom(): number {
40
- return this.viewer.getZoom()
38
+ return this.viewer.getZoom();
41
39
  }
42
40
  set zoom(val: number) {
43
- this.viewer.setZoom(val)
41
+ this.viewer.setZoom(val);
44
42
  }
45
43
 
46
44
  constructor(viewer: any) {
47
- super()
48
- this.viewer = viewer
49
- this.container = viewer.getContainer()
50
- this.container.children.item(1).appendChild(this.htmllayer)
51
- this.cursor = 'default'
52
- bindEvent(this)
45
+ super();
46
+ this.viewer = viewer;
47
+ this.container = viewer.getContainer();
48
+ this.container.children.item(1).appendChild(this.htmllayer);
49
+ this.cursor = "default";
50
+ bindEvent(this);
53
51
  }
54
52
 
55
-
56
-
57
53
  canvasTgeography(p: number[]): number[] {
58
54
  const res = this.viewer.getTDSpaceCoord({ point: p, disableLayer: true });
59
55
  return [res.lngLat.lng, res.lngLat.lat, 0];
@@ -64,27 +60,41 @@ export class MineMap extends MapCombine {
64
60
  }
65
61
 
66
62
  createPoint<K>(option?: Partial<PointOption<K>>): Point<K> {
67
- const e = new Point(this, option)
68
- drawPoint(this, e)
69
- return e
63
+ const e = new Point(this, option);
64
+ drawPoint(this, e);
65
+ return e;
70
66
  }
71
67
 
72
68
  createPolyline<K>(option?: Partial<PolylineOption<K>>): Polyline<K> {
73
- const e = new Polyline(this, option)
74
- drawPolyline(this, e)
75
- return e
69
+ const e = new Polyline(this, option);
70
+ drawPolyline(this, e);
71
+ return e;
76
72
  }
77
73
  createPolygon<K>(option?: Partial<PolygonOption<K>>): Polygon<K> {
78
- const e = new Polygon(this, option)
79
- drawPolygon(this, e)
80
- return e
74
+ const e = new Polygon(this, option);
75
+ drawPolygon(this, e);
76
+ return e;
81
77
  }
82
78
 
83
- createTile3D(option?: Partial<Tile3DOption>): Tile3D {
84
- const e = new Tile3D(this, option)
85
- drawTile3D(this, e)
86
- return e
79
+ /**
80
+ * 所有点位移动至视口,调整位置及层级
81
+ * @param points
82
+ * @param opt
83
+ * @param {Array<number> = [0,0,0,0]} opt.avoid 距离边框的内边距,顺序:上、下、左、右
84
+ */
85
+ flyToViewer(points, opt = { avoid: [0, 0, 0, 0] }) {
86
+ const rectangle = this.getBounds(points, { canvas: this.viewer.getCanvas(), ...opt });
87
+
88
+ // 设置地图视图,使用调整后的边界范围
89
+ this.viewer.fitBounds([
90
+ [rectangle[0], rectangle[1]],
91
+ [rectangle[2], rectangle[3]],
92
+ ]);
87
93
  }
88
94
 
95
+ createTile3D(option?: Partial<Tile3DOption>): Tile3D {
96
+ const e = new Tile3D(this, option);
97
+ drawTile3D(this, e);
98
+ return e;
99
+ }
89
100
  }
90
-
@@ -1,14 +1,21 @@
1
- import { MapCombine } from "../basic/MapCombine";
2
- import { PointOption, Point } from "../basic/Point";
1
+ import * as ol from "ol/index.js";
3
2
  import Map from "ol/Map.js";
4
3
  import View from "ol/View";
5
4
  import XYZ from "ol/source/XYZ";
6
5
  import Tile from "ol/layer/Tile";
7
6
  import DragPan from "ol/interaction/DragPan";
8
- import { Projection } from "../utils/Projection";
9
7
  import VectorSource from "ol/source/Vector";
10
8
  import VectorLayer from "ol/layer/Vector";
11
9
  import { fromLonLat } from "ol/proj";
10
+ import * as olGeom from "ol/geom";
11
+ import * as olSource from "ol/source";
12
+ import * as olStyle from "ol/style";
13
+ import * as olLayer from "ol/layer";
14
+ import * as olExtent from "ol/extent";
15
+
16
+ import { MapCombine } from "../basic/MapCombine";
17
+ import { PointOption, Point } from "../basic/Point";
18
+ import { Projection } from "../utils/Projection";
12
19
  import { bindEvent } from "./OpenlayerEvent";
13
20
  import { PolylineOption, Polyline } from "../basic/Polyline";
14
21
  import DoubleClickZoom from "ol/interaction/DoubleClickZoom";
@@ -39,6 +46,7 @@ export class OpenlayerMap extends MapCombine {
39
46
  option: IOpenlayerOption;
40
47
  offset: number[];
41
48
  fov = 0.9272952180016121;
49
+ isFromLonLat = true;
42
50
  get cursor(): string {
43
51
  return this.container.style.cursor;
44
52
  }
@@ -113,8 +121,9 @@ export class OpenlayerMap extends MapCombine {
113
121
  this.cursor = "default";
114
122
 
115
123
  const { center } = this;
116
- this.offset = fromLonLat(center);
117
-
124
+ const proj = this.viewer.getView().getProjection().getCode();
125
+ this.isFromLonLat = (proj === "EPSG:3857" || proj === "EPSG:4326");
126
+ this.offset = this.getFromLonLat(center);
118
127
  this.vectors = new VectorSource();
119
128
  this.viewer.addLayer(
120
129
  new VectorLayer({
@@ -135,6 +144,11 @@ export class OpenlayerMap extends MapCombine {
135
144
  bindEvent(this);
136
145
  }
137
146
 
147
+
148
+ getFromLonLat(lonLat) {
149
+ return this.isFromLonLat ? fromLonLat(lonLat) : lonLat;
150
+ }
151
+
138
152
  createPoint<K>(option?: Partial<PointOption<K>>): Point<K> {
139
153
  const e = new Point(this, option);
140
154
  drawPoint(this, e);
@@ -163,12 +177,50 @@ export class OpenlayerMap extends MapCombine {
163
177
  // // this.meterPerPixel = height / this.container.offsetHeight;
164
178
  // }
165
179
 
180
+ /**
181
+ * 所有点位移动至视口,调整位置及层级
182
+ * @param points
183
+ * @param opt
184
+ * @param {Array<number> = [0,0,0,0]} opt.avoid 距离边框的内边距,顺序:上、下、左、右
185
+ */
186
+ flyToViewer(points, opt = { avoid: [0, 0, 0, 0] }) {
187
+ const { avoid } = opt || {};
188
+ // 创建 Feature 数组
189
+ const features = points.map((point) => {
190
+ const [lon, lat] = point;
191
+ const coord = this.getFromLonLat([lon, lat]);
192
+ return new ol.Feature({
193
+ geometry: new olGeom.Point(coord),
194
+ });
195
+ });
196
+
197
+ // 创建 VectorSource
198
+ const source = new olSource.Vector({
199
+ features: features,
200
+ });
201
+
202
+ // 计算边界范围
203
+ const extent = source.getExtent();
204
+
205
+ // 调整边界范围
206
+ olExtent.buffer(extent, this.viewer.getView().getResolution(), extent);
207
+
208
+ // 设置地图视图
209
+ this.viewer.getView().fit(extent, {
210
+ // avoid {Array<number> = [0,0,0,0]} opt.avoid 距离边框的内边距,顺序:上、下、左、右
211
+ // 上 右 下 左
212
+ padding: [avoid[0], avoid[3], avoid[1], avoid[2]],
213
+ duration: 1000,
214
+ ...opt,
215
+ });
216
+ }
217
+
166
218
  geographyTspace(p: number[]): number[] {
167
219
  const { offset } = this;
168
220
  return [Projection.lonToX(p[0]) - offset[0], Projection.latToY(p[1]) - offset[1], p[2] ?? 0];
169
221
  }
170
222
  geographyTcanvas(p: number[]): number[] {
171
- const pixel = this.viewer.getPixelFromCoordinate(fromLonLat(p));
223
+ const pixel = this.viewer.getPixelFromCoordinate(this.getFromLonLat(p));
172
224
  if (pixel) {
173
225
  return [pixel[0], pixel[1]];
174
226
  } else {
@@ -9,7 +9,7 @@ import VectorLayer from "ol/layer/Vector";
9
9
  const RD = 0.017453292519943295
10
10
 
11
11
  export function drawPoint(map: OpenlayerMap, point: Point<unknown>) {
12
- const { viewer, event } = map
12
+ const { viewer, event, getFromLonLat } = map
13
13
  let status = 0
14
14
 
15
15
  const source = new VectorSource();
@@ -67,7 +67,7 @@ export function drawPoint(map: OpenlayerMap, point: Point<unknown>) {
67
67
  feature.set('event', _event, true)
68
68
  if (point.coordinates) {
69
69
  status = 2
70
- geometry.setCoordinates(fromLonLat(point.coordinates))
70
+ geometry.setCoordinates(getFromLonLat(point.coordinates))
71
71
  layer.setZIndex(point.coordinates[2] ?? 1)
72
72
  point.event.trigger('data-loaded')
73
73
  source.addFeature(feature)
@@ -87,7 +87,7 @@ export function drawPoint(map: OpenlayerMap, point: Point<unknown>) {
87
87
  break;
88
88
  case 'coordinates':
89
89
  if (point.coordinates) {
90
- geometry.setCoordinates(fromLonLat(point.coordinates))
90
+ geometry.setCoordinates(getFromLonLat(point.coordinates))
91
91
  layer.setZIndex(point.coordinates[2])
92
92
  switch (status) {
93
93
  case 0:
@@ -138,16 +138,16 @@ export function drawPoint(map: OpenlayerMap, point: Point<unknown>) {
138
138
  }
139
139
 
140
140
  const onMouseMove = () => {
141
- const coordinates = [event.geography[0], event.geography[1], point.height]
141
+ const coordinates = [event.geography[0], event.geography[1], point.height];
142
142
  switch (status) {
143
143
  case 0:
144
144
  status = 1
145
- geometry.setCoordinates(fromLonLat(coordinates))
145
+ geometry.setCoordinates(getFromLonLat(coordinates))
146
146
  source.addFeature(feature)
147
147
  break;
148
148
  case 1:
149
149
  case 3:
150
- geometry.setCoordinates(fromLonLat(coordinates))
150
+ geometry.setCoordinates(getFromLonLat(coordinates))
151
151
  break
152
152
  }
153
153
  }
@@ -34,7 +34,7 @@ const styleVirtual = new Style({
34
34
 
35
35
 
36
36
  export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
37
- const { event, viewer, vectors } = map
37
+ const { event, viewer, vectors, getFromLonLat } = map
38
38
 
39
39
  const source = new VectorSource();
40
40
 
@@ -93,7 +93,7 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
93
93
  feature.set('event', _event, true)
94
94
  if (polygon.coordinates) {
95
95
  status = 2
96
- geometry.setCoordinates([polygon.coordinates.map(e => fromLonLat(e))])
96
+ geometry.setCoordinates([polygon.coordinates.map(e => getFromLonLat(e))])
97
97
  layer.setZIndex(polygon.coordinates[0][2] ?? 1)
98
98
  source.addFeature(feature)
99
99
  }
@@ -116,7 +116,7 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
116
116
  break;
117
117
  case 'coordinates':
118
118
  if (polygon.coordinates) {
119
- geometry.setCoordinates([polygon.coordinates.map(e => fromLonLat(e))])
119
+ geometry.setCoordinates([polygon.coordinates.map(e => getFromLonLat(e))])
120
120
  layer.setZIndex(polygon.coordinates[0][2] ?? 1)
121
121
  switch (status) {
122
122
  case 0:
@@ -158,11 +158,11 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
158
158
  switch (status) {
159
159
  case 1:
160
160
  cache.pop()
161
- cache.push(fromLonLat(event.geography))
161
+ cache.push(getFromLonLat(event.geography))
162
162
  geometry.setCoordinates([cache])
163
163
  break
164
164
  case 4:
165
- activeNode.update(fromLonLat(event.geography))
165
+ activeNode.update(getFromLonLat(event.geography))
166
166
  geometry.setCoordinates([editor.getCoordinates()])
167
167
  break;
168
168
  }
@@ -172,8 +172,7 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
172
172
  switch (status) {
173
173
  case 0:
174
174
  status = 1
175
-
176
- cache = [fromLonLat(event.geography)]
175
+ cache = [getFromLonLat(event.geography)]
177
176
  cache.push(cache[0])
178
177
  geometry.setCoordinates([cache])
179
178
  source.addFeature(feature)
@@ -30,7 +30,7 @@ const styleVirtual = new Style({
30
30
  });
31
31
 
32
32
  export function drawPolyline(map: OpenlayerMap, polyline: Polyline<unknown>) {
33
- const { event, viewer } = map
33
+ const { event, viewer, getFromLonLat } = map
34
34
 
35
35
  const source = new VectorSource();
36
36
 
@@ -86,7 +86,7 @@ export function drawPolyline(map: OpenlayerMap, polyline: Polyline<unknown>) {
86
86
  feature.set('event', _event, true)
87
87
  if (polyline.coordinates) {
88
88
  status = 2
89
- geometry.setCoordinates(polyline.coordinates.map(e => fromLonLat(e)))
89
+ geometry.setCoordinates(polyline.coordinates.map(e => getFromLonLat(e)))
90
90
  layer.setZIndex(polyline.coordinates[0][2] ?? 1)
91
91
  source.addFeature(feature)
92
92
  }
@@ -106,7 +106,7 @@ export function drawPolyline(map: OpenlayerMap, polyline: Polyline<unknown>) {
106
106
  break;
107
107
  case 'coordinates':
108
108
  if (polyline.coordinates) {
109
- geometry.setCoordinates(polyline.coordinates.map(e => fromLonLat(e)))
109
+ geometry.setCoordinates(polyline.coordinates.map(e => getFromLonLat(e)))
110
110
  layer.setZIndex(polyline.coordinates[0][2] ?? 1)
111
111
  switch (status) {
112
112
  case 0:
@@ -147,11 +147,11 @@ export function drawPolyline(map: OpenlayerMap, polyline: Polyline<unknown>) {
147
147
  switch (status) {
148
148
  case 1:
149
149
  cache.pop()
150
- cache.push(fromLonLat(event.geography))
150
+ cache.push(getFromLonLat(event.geography))
151
151
  geometry.setCoordinates(cache)
152
152
  break
153
153
  case 4:
154
- activeNode.update(fromLonLat(event.geography))
154
+ activeNode.update(getFromLonLat(event.geography))
155
155
  geometry.setCoordinates(editor.getCoordinates())
156
156
  break;
157
157
  }
@@ -161,8 +161,8 @@ export function drawPolyline(map: OpenlayerMap, polyline: Polyline<unknown>) {
161
161
  switch (status) {
162
162
  case 0:
163
163
  status = 1
164
- _event.silent = true
165
- cache = [fromLonLat(event.geography)]
164
+ _event.silent = true;
165
+ cache = [getFromLonLat(event.geography)]
166
166
  cache.push(cache[0])
167
167
  geometry.setCoordinates(cache)
168
168
  source.addFeature(feature)
@@ -0,0 +1,47 @@
1
+ /**
2
+ * 所有点位移动至视口,活动边界经纬度
3
+ * @param points
4
+ * @param opt
5
+ * @param {Array<number> = [0,0,0,0]} opt.avoid 距离边框的内边距,顺序:上、下、左、右
6
+ */
7
+ export const getBounds = function (points, opt) {
8
+ const {
9
+ /**
10
+ * avoid (Array<number> = [0,0,0,0]) 距离边框的内边距,顺序:上、下、左、右
11
+ */
12
+ avoid = [0, 0, 0, 0],
13
+ canvas,
14
+ } = opt;
15
+
16
+ // 计算边界框
17
+ let minLon = Infinity;
18
+ let maxLon = -Infinity;
19
+ let minLat = Infinity;
20
+ let maxLat = -Infinity;
21
+
22
+ points.forEach((point) => {
23
+ const [longitude, latitude] = point;
24
+ minLon = Math.min(minLon, longitude);
25
+ maxLon = Math.max(maxLon, longitude);
26
+ minLat = Math.min(minLat, latitude);
27
+ maxLat = Math.max(maxLat, latitude);
28
+ });
29
+
30
+ // 获取画布尺
31
+ const canvasWidth = canvas.clientWidth;
32
+ const canvasHeight = canvas.clientHeight;
33
+
34
+ // 估算像素到地理范围的转换比例
35
+ const lonRange = maxLon - minLon;
36
+ const latRange = maxLat - minLat;
37
+ const lonPixelRatio = lonRange / canvasWidth;
38
+ const latPixelRatio = latRange / canvasHeight;
39
+
40
+ // 根据像素距离调整边界框
41
+ minLon -= avoid[2] * lonPixelRatio;
42
+ maxLon += avoid[3] * lonPixelRatio;
43
+ minLat -= avoid[1] * latPixelRatio;
44
+ maxLat += avoid[0] * latPixelRatio;
45
+
46
+ return [minLon, minLat, maxLon, maxLat];
47
+ };