my-openlayer 2.1.6 → 2.1.8

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.
@@ -30,6 +30,8 @@ export default class MapTools {
30
30
  static getLayerByLayerName(map: Map, layerName: string | string[]): (VectorLayer<VectorSource> | BaseLayer | ImageLayer<ImageSource>)[];
31
31
  /**
32
32
  * 设置地图裁剪
33
+ * 使用 Canvas clip 实现裁剪,支持多个闭合区域
34
+ * 注意:此方法会修改 baseLayer 的 prerender 和 postrender 事件
33
35
  */
34
36
  static setMapClip(baseLayer: any, data: MapJSONData): any;
35
37
  /**
package/core/MapTools.js CHANGED
@@ -1,9 +1,5 @@
1
1
  "use strict";
2
- import VectorLayer from "ol/layer/Vector";
3
- import VectorSource from "ol/source/Vector";
4
2
  import GeoJSON from "ol/format/GeoJSON";
5
- import { Fill, Style } from "ol/style";
6
- import { getVectorContext } from "ol/render";
7
3
  import { ErrorHandler, ErrorType } from "../utils/ErrorHandler";
8
4
  import { ValidationUtils } from "../utils/ValidationUtils";
9
5
  /**
@@ -69,26 +65,59 @@ class MapTools {
69
65
  }
70
66
  /**
71
67
  * 设置地图裁剪
68
+ * 使用 Canvas clip 实现裁剪,支持多个闭合区域
69
+ * 注意:此方法会修改 baseLayer 的 prerender 和 postrender 事件
72
70
  */
73
71
  static setMapClip(baseLayer, data) {
74
- const clipLayer = new VectorLayer({
75
- style: null,
76
- source: new VectorSource({
77
- features: new GeoJSON().readFeatures(data)
78
- })
79
- });
80
- const style = new Style({
81
- fill: new Fill({
82
- color: 'transparent'
83
- })
84
- });
72
+ const features = new GeoJSON().readFeatures(data);
85
73
  baseLayer.on("prerender", (event) => {
86
- const vectorContext = getVectorContext(event);
87
- event.context.globalCompositeOperation = 'source-over';
88
74
  const ctx = event.context;
75
+ // 获取坐标转换矩阵 (pixel = coordinate * transform)
76
+ // 注意:OpenLayers 的 transform 可能包含 pixelRatio,也可能不包含,取决于版本
77
+ // 在现代版本中,event.frameState.coordinateToPixelTransform 通常用于将地理坐标转换为 Canvas 像素坐标
78
+ const transform = event.frameState.coordinateToPixelTransform;
89
79
  ctx.save();
90
- clipLayer.getSource()?.forEachFeature(function (feature) {
91
- vectorContext.drawFeature(feature, style);
80
+ ctx.beginPath();
81
+ features.forEach((feature) => {
82
+ const geometry = feature.getGeometry();
83
+ if (!geometry)
84
+ return;
85
+ const type = geometry.getType();
86
+ const coordinates = geometry.getCoordinates();
87
+ // 辅助函数:绘制单个线性环
88
+ const drawRing = (ringCoords) => {
89
+ if (!ringCoords || ringCoords.length === 0)
90
+ return;
91
+ for (let i = 0; i < ringCoords.length; i++) {
92
+ const coord = ringCoords[i];
93
+ // 手动应用变换: pixelX = x * m0 + y * m1 + m4
94
+ // pixelY = x * m2 + y * m3 + m5
95
+ // transform 数组结构: [m0, m1, m2, m3, m4, m5]
96
+ const pixelX = coord[0] * transform[0] + coord[1] * transform[1] + transform[4];
97
+ const pixelY = coord[0] * transform[2] + coord[1] * transform[3] + transform[5];
98
+ if (i === 0) {
99
+ ctx.moveTo(pixelX, pixelY);
100
+ }
101
+ else {
102
+ ctx.lineTo(pixelX, pixelY);
103
+ }
104
+ }
105
+ ctx.closePath();
106
+ };
107
+ if (type === 'MultiPolygon') {
108
+ // MultiPolygon: [Polygon, Polygon] -> Polygon: [OuterRing, InnerRing, ...]
109
+ coordinates.forEach((polygonCoords) => {
110
+ polygonCoords.forEach((ringCoords) => {
111
+ drawRing(ringCoords);
112
+ });
113
+ });
114
+ }
115
+ else if (type === 'Polygon') {
116
+ // Polygon: [OuterRing, InnerRing, ...]
117
+ coordinates.forEach((ringCoords) => {
118
+ drawRing(ringCoords);
119
+ });
120
+ }
92
121
  });
93
122
  ctx.clip();
94
123
  });
@@ -96,9 +125,6 @@ class MapTools {
96
125
  const ctx = event.context;
97
126
  ctx.restore();
98
127
  });
99
- clipLayer.getSource()?.on('addfeature', function () {
100
- baseLayer.setExtent(clipLayer.getSource()?.getExtent());
101
- });
102
128
  return baseLayer;
103
129
  }
104
130
  /**
package/core/Point.js CHANGED
@@ -118,6 +118,7 @@ export default class Point {
118
118
  const pointFeature = new Feature({
119
119
  rawData: item,
120
120
  type: options.layerName,
121
+ layerName: options.layerName,
121
122
  geometry: new olPoint([item.lgtd, item.lttd])
122
123
  });
123
124
  pointFeature.setStyle(this.createPointStyle(options, item));
package/core/Polygon.js CHANGED
@@ -4,7 +4,7 @@ import VectorSource from "ol/source/Vector";
4
4
  import GeoJSON from "ol/format/GeoJSON";
5
5
  import { Fill, Stroke, Style, Text } from "ol/style";
6
6
  import { Image as ImageLayer, Heatmap } from "ol/layer";
7
- import { Geometry, LinearRing, Point } from "ol/geom";
7
+ import { LinearRing, Point } from "ol/geom";
8
8
  import { fromExtent } from "ol/geom/Polygon";
9
9
  import Feature from "ol/Feature";
10
10
  import ImageStatic from "ol/source/ImageStatic";
@@ -350,34 +350,27 @@ export default class Polygon {
350
350
  }
351
351
  return group;
352
352
  }
353
- /** 擦除操作 **/
354
- function erase(geom, view) {
355
- const part = getCoordsGroup(geom);
356
- if (!part) {
357
- return;
353
+ /** 擦除操作 - 创建遮罩多边形 **/
354
+ function erase(geometries, view) {
355
+ // 收集所有几何图形的坐标环
356
+ let allParts = [];
357
+ geometries.forEach(geom => {
358
+ const parts = getCoordsGroup(geom);
359
+ if (parts && parts.length > 0) {
360
+ allParts = allParts.concat(parts);
361
+ }
362
+ });
363
+ if (allParts.length === 0) {
364
+ return null;
358
365
  }
359
366
  const extent = view.getProjection().getExtent();
360
367
  const polygonRing = fromExtent(extent);
361
- part.forEach((item) => {
368
+ allParts.forEach((item) => {
362
369
  const linearRing = new LinearRing(item);
363
370
  polygonRing.appendLinearRing(linearRing);
364
371
  });
365
372
  return polygonRing;
366
373
  }
367
- /** 添加遮罩 **/
368
- function createShade(geom, view) {
369
- if (geom instanceof Geometry) {
370
- const source = geom.clone();
371
- const polygon = erase(source, view);
372
- const feature = new Feature({
373
- geometry: polygon
374
- });
375
- return {
376
- feature,
377
- shade: source
378
- };
379
- }
380
- }
381
374
  // 遮罩样式
382
375
  const shadeStyle = new Style({
383
376
  fill: new Fill({
@@ -398,13 +391,39 @@ export default class Polygon {
398
391
  });
399
392
  this.map.addLayer(vtLayer);
400
393
  const features = new GeoJSON().readFeatures(data);
401
- const ft = features[0];
402
- const bound = ft.getGeometry();
403
- const result = createShade(bound, this.map.getView());
404
- if (result) {
405
- vtSource.addFeature(result.feature);
406
- if (options?.extent)
407
- this.map.getView().fit(result.shade);
394
+ // 收集所有要素的几何图形
395
+ const geometries = [];
396
+ features.forEach(feature => {
397
+ const geometry = feature.getGeometry();
398
+ if (geometry) {
399
+ geometries.push(geometry);
400
+ }
401
+ });
402
+ if (geometries.length > 0) {
403
+ // 创建遮罩
404
+ const polygon = erase(geometries, this.map.getView());
405
+ if (polygon) {
406
+ const feature = new Feature({
407
+ geometry: polygon
408
+ });
409
+ vtSource.addFeature(feature);
410
+ // 如果需要适应视图,计算所有几何图形的合并范围
411
+ if (options?.extent) {
412
+ let totalExtent = geometries[0].getExtent();
413
+ for (let i = 1; i < geometries.length; i++) {
414
+ // 注意:这里需要导入 extend 函数,或者使用简单的 extent 合并逻辑
415
+ // 由于 openlayers 的 extent 是 [minx, miny, maxx, maxy]
416
+ const ext = geometries[i].getExtent();
417
+ totalExtent = [
418
+ Math.min(totalExtent[0], ext[0]),
419
+ Math.min(totalExtent[1], ext[1]),
420
+ Math.max(totalExtent[2], ext[2]),
421
+ Math.max(totalExtent[3], ext[3])
422
+ ];
423
+ }
424
+ this.map.getView().fit(totalExtent);
425
+ }
426
+ }
408
427
  }
409
428
  }
410
429
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "my-openlayer",
3
3
  "private": false,
4
- "version": "2.1.6",
4
+ "version": "2.1.8",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",