@hzab/map-combine 0.4.2-alpha.0 → 0.4.2-alpha.11
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 +7 -0
- package/package.json +5 -5
- package/src/amap/AMap.ts +313 -306
- package/src/amap/AMapEvent.ts +110 -54
- package/src/amap/AMapPoint.ts +140 -143
- package/src/amap/AMapPolygon.ts +214 -195
- package/src/amap/AMapPolyline.ts +199 -185
- package/src/basic/BasicBusiness.ts +5 -5
- package/src/basic/BasicModel.ts +49 -0
- package/src/basic/MapCombine.ts +4 -0
- package/src/basic/MapElement.ts +2 -1
- package/src/basic/MapEvent.ts +5 -0
- package/src/basic/Point.ts +1 -0
- package/src/basic/PointAggregation.tsx +23 -11
- package/src/basic/ReactPopup.tsx +3 -0
- package/src/cesium/CesiumEvent.ts +97 -84
- package/src/cesium/CesiumMap.ts +355 -347
- package/src/cesium/CesiumModel.ts +64 -0
- package/src/cesium/CesiumPoint.ts +3 -0
- package/src/cesium/CesiumPolygon.ts +2 -0
- package/src/cesium/CesiumPolyline.ts +185 -47
- package/src/cesium/CesiumTile3D.ts +222 -225
- package/src/mine/MineEvent.ts +70 -46
- package/src/mine/MineMap.ts +52 -1
- package/src/mine/MinePoint.ts +7 -1
- package/src/mine/MinePolygon.ts +6 -1
- package/src/mine/MinePolyline.ts +6 -1
- package/src/openlayer/OpenlayerEvent.ts +109 -87
- package/src/openlayer/OpenlayerMap.ts +287 -287
- package/src/openlayer/OpenlayerPoint.ts +6 -1
- package/src/openlayer/OpenlayerPolygon.ts +34 -24
- package/src/openlayer/OpenlayerPolyline.ts +10 -3
- package/src/utils/color.ts +49 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/points-viewer.ts +27 -1
- package/src/utils/turfjs-utils.ts +52 -0
- package/src/utils/types.d.ts +12 -0
|
@@ -10,26 +10,10 @@ import iconPoint from "../assets/point.png";
|
|
|
10
10
|
import iconAdd from "../assets/add.png";
|
|
11
11
|
import Point from "ol/geom/Point.js";
|
|
12
12
|
import { ChainNode, PolygonEditor } from "../utils/PolygonEditor";
|
|
13
|
-
const styleNode = new Style({
|
|
14
|
-
image: new Icon({
|
|
15
|
-
width: 16,
|
|
16
|
-
height: 16,
|
|
17
|
-
src: iconPoint,
|
|
18
|
-
crossOrigin: "anonymous",
|
|
19
|
-
}),
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const styleVirtual = new Style({
|
|
23
|
-
image: new Icon({
|
|
24
|
-
width: 16,
|
|
25
|
-
height: 16,
|
|
26
|
-
src: iconAdd,
|
|
27
|
-
crossOrigin: "anonymous",
|
|
28
|
-
}),
|
|
29
|
-
});
|
|
30
13
|
|
|
31
14
|
export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
|
|
32
|
-
const { event, viewer, vectors,
|
|
15
|
+
const { event, viewer, vectors, isFromLonLat } = map;
|
|
16
|
+
// getFromLonLat 使用 map.getFromLonLat 调用,保证 this 指向正确
|
|
33
17
|
|
|
34
18
|
const source = new VectorSource();
|
|
35
19
|
|
|
@@ -42,7 +26,12 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
|
|
|
42
26
|
let status = 0;
|
|
43
27
|
let skip = 0;
|
|
44
28
|
|
|
45
|
-
const feature = new Feature(
|
|
29
|
+
const feature = new Feature({
|
|
30
|
+
userData: {
|
|
31
|
+
name: polygon.name,
|
|
32
|
+
target: polygon,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
46
35
|
const geometry = new OlPolygon([
|
|
47
36
|
[
|
|
48
37
|
[0, 0],
|
|
@@ -62,6 +51,27 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
|
|
|
62
51
|
stroke,
|
|
63
52
|
fill,
|
|
64
53
|
});
|
|
54
|
+
const styleNode = new Style({
|
|
55
|
+
image: new Icon({
|
|
56
|
+
width: 16,
|
|
57
|
+
height: 16,
|
|
58
|
+
src: iconPoint,
|
|
59
|
+
crossOrigin: "anonymous",
|
|
60
|
+
}),
|
|
61
|
+
// 保证编辑的点位高于线
|
|
62
|
+
zIndex: style.getZIndex() + 5,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const styleVirtual = new Style({
|
|
66
|
+
image: new Icon({
|
|
67
|
+
width: 16,
|
|
68
|
+
height: 16,
|
|
69
|
+
src: iconAdd,
|
|
70
|
+
crossOrigin: "anonymous",
|
|
71
|
+
}),
|
|
72
|
+
// 保证编辑的点位高于线
|
|
73
|
+
zIndex: style.getZIndex() + 5,
|
|
74
|
+
});
|
|
65
75
|
|
|
66
76
|
const _event = {
|
|
67
77
|
cursor: polygon.cursor,
|
|
@@ -95,7 +105,7 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
|
|
|
95
105
|
feature.set("event", _event, true);
|
|
96
106
|
if (polygon.coordinates) {
|
|
97
107
|
status = 2;
|
|
98
|
-
geometry.setCoordinates([polygon.coordinates.map((e) => getFromLonLat(e, isFromLonLat))]);
|
|
108
|
+
geometry.setCoordinates([polygon.coordinates.map((e) => map.getFromLonLat(e, isFromLonLat))]);
|
|
99
109
|
layer.setZIndex(polygon.coordinates[0][2] ?? 1);
|
|
100
110
|
source.addFeature(feature);
|
|
101
111
|
}
|
|
@@ -115,7 +125,7 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
|
|
|
115
125
|
break;
|
|
116
126
|
case "coordinates":
|
|
117
127
|
if (polygon.coordinates) {
|
|
118
|
-
geometry.setCoordinates([polygon.coordinates.map((e) => getFromLonLat(e, isFromLonLat))]);
|
|
128
|
+
geometry.setCoordinates([polygon.coordinates.map((e) => map.getFromLonLat(e, isFromLonLat))]);
|
|
119
129
|
layer.setZIndex(polygon.coordinates[0][2] ?? 1);
|
|
120
130
|
switch (status) {
|
|
121
131
|
case 0:
|
|
@@ -157,11 +167,11 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
|
|
|
157
167
|
switch (status) {
|
|
158
168
|
case 1:
|
|
159
169
|
cache.pop();
|
|
160
|
-
cache.push(getFromLonLat(event.geography));
|
|
170
|
+
cache.push(map.getFromLonLat(event.geography));
|
|
161
171
|
geometry.setCoordinates([cache]);
|
|
162
172
|
break;
|
|
163
173
|
case 4:
|
|
164
|
-
activeNode.update(getFromLonLat(event.geography));
|
|
174
|
+
activeNode.update(map.getFromLonLat(event.geography));
|
|
165
175
|
geometry.setCoordinates([editor.getCoordinates()]);
|
|
166
176
|
break;
|
|
167
177
|
}
|
|
@@ -171,7 +181,7 @@ export function drawPolygon(map: OpenlayerMap, polygon: Polygon<unknown>) {
|
|
|
171
181
|
switch (status) {
|
|
172
182
|
case 0:
|
|
173
183
|
status = 1;
|
|
174
|
-
cache = [getFromLonLat(event.geography)];
|
|
184
|
+
cache = [map.getFromLonLat(event.geography)];
|
|
175
185
|
cache.push(cache[0]);
|
|
176
186
|
geometry.setCoordinates([cache]);
|
|
177
187
|
source.addFeature(feature);
|
|
@@ -25,7 +25,12 @@ export function drawPolyline(map: OpenlayerMap, polyline: Polyline<unknown>) {
|
|
|
25
25
|
let status = 0;
|
|
26
26
|
let skip = 0;
|
|
27
27
|
|
|
28
|
-
const feature = new Feature(
|
|
28
|
+
const feature = new Feature({
|
|
29
|
+
userData: {
|
|
30
|
+
name: polyline.name,
|
|
31
|
+
target: polyline,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
29
34
|
const geometry = new LineString([
|
|
30
35
|
[0, 0],
|
|
31
36
|
[0, 0],
|
|
@@ -48,7 +53,7 @@ export function drawPolyline(map: OpenlayerMap, polyline: Polyline<unknown>) {
|
|
|
48
53
|
src: iconPoint,
|
|
49
54
|
crossOrigin: "anonymous",
|
|
50
55
|
}),
|
|
51
|
-
//
|
|
56
|
+
// 保证编辑的点位高于线
|
|
52
57
|
zIndex: style.getZIndex() + 5,
|
|
53
58
|
});
|
|
54
59
|
|
|
@@ -59,11 +64,13 @@ export function drawPolyline(map: OpenlayerMap, polyline: Polyline<unknown>) {
|
|
|
59
64
|
src: iconAdd,
|
|
60
65
|
crossOrigin: "anonymous",
|
|
61
66
|
}),
|
|
62
|
-
//
|
|
67
|
+
// 保证编辑的点位高于线
|
|
63
68
|
zIndex: style.getZIndex() + 5,
|
|
64
69
|
});
|
|
65
70
|
|
|
66
71
|
const _event = {
|
|
72
|
+
name: polyline.name,
|
|
73
|
+
target: polyline,
|
|
67
74
|
cursor: polyline.cursor,
|
|
68
75
|
silent: polyline.silent,
|
|
69
76
|
onPointerIn() {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 解析十六进制颜色字符串,拆分为颜色值和透明度
|
|
3
|
+
* @param {string} hexColor - 十六进制颜色字符串,支持格式:#RGB, #RRGGBB, #RRGGBBAA, #RGBA
|
|
4
|
+
* @param {number} defaultOpacity - 默认透明度(0-1),当颜色没有透明度时使用
|
|
5
|
+
* @returns {Object} { color: string, opacity: number }
|
|
6
|
+
* @throws {Error} 如果颜色格式无效
|
|
7
|
+
*/
|
|
8
|
+
export function parseHexColor(hexColor, defaultOpacity = 1) {
|
|
9
|
+
// 移除开头的 # 号(如果有)
|
|
10
|
+
let hex = hexColor.replace(/^#/, "");
|
|
11
|
+
|
|
12
|
+
// 验证是否为有效的十六进制字符串
|
|
13
|
+
if (!/^[0-9a-fA-F]+$/.test(hex)) {
|
|
14
|
+
throw new Error(`无效的颜色格式: "${hexColor}"`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let color = "";
|
|
18
|
+
let opacity = defaultOpacity;
|
|
19
|
+
|
|
20
|
+
switch (hex.length) {
|
|
21
|
+
case 3: // #RGB
|
|
22
|
+
color = `#${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}`;
|
|
23
|
+
opacity = defaultOpacity;
|
|
24
|
+
break;
|
|
25
|
+
|
|
26
|
+
case 4: // #RGBA
|
|
27
|
+
color = `#${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}`;
|
|
28
|
+
opacity = parseInt(hex[3] + hex[3], 16) / 255;
|
|
29
|
+
break;
|
|
30
|
+
|
|
31
|
+
case 6: // #RRGGBB
|
|
32
|
+
color = `#${hex}`;
|
|
33
|
+
opacity = defaultOpacity;
|
|
34
|
+
break;
|
|
35
|
+
|
|
36
|
+
case 8: // #RRGGBBAA
|
|
37
|
+
color = `#${hex.slice(0, 6)}`;
|
|
38
|
+
opacity = parseInt(hex.slice(6, 8), 16) / 255;
|
|
39
|
+
break;
|
|
40
|
+
|
|
41
|
+
default:
|
|
42
|
+
throw new Error(`不支持的十六进制颜色长度: "${hexColor}",长度必须为 3、4、6 或 8`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 确保透明度在 0-1 范围内
|
|
46
|
+
opacity = Math.max(0, Math.min(1, opacity));
|
|
47
|
+
|
|
48
|
+
return { color, opacity };
|
|
49
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -43,5 +43,31 @@ export const getBounds = function (points, opt) {
|
|
|
43
43
|
minLat -= avoid[1] * latPixelRatio;
|
|
44
44
|
maxLat += avoid[0] * latPixelRatio;
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
// 根据 maxZoom 计算最小矩形范围
|
|
47
|
+
const minRange = getMinRangeFromZoom(opt.maxZoom);
|
|
48
|
+
const centerLon = (minLon + maxLon) / 2;
|
|
49
|
+
const centerLat = (minLat + maxLat) / 2;
|
|
50
|
+
|
|
51
|
+
// 确保矩形范围不小于最小值 解决点位距离过近导致异常缩放问题
|
|
52
|
+
let finalWest = Math.min(minLon, centerLon - minRange / 2);
|
|
53
|
+
let finalEast = Math.max(maxLon, centerLon + minRange / 2);
|
|
54
|
+
let finalSouth = Math.min(minLat, centerLat - minRange / 2);
|
|
55
|
+
let finalNorth = Math.max(maxLat, centerLat + minRange / 2);
|
|
56
|
+
|
|
57
|
+
return [finalWest, finalSouth, finalEast, finalNorth];
|
|
47
58
|
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 根据 maxZoom 计算出一个“最小”的经纬度跨度
|
|
62
|
+
* @param zoom
|
|
63
|
+
* @returns
|
|
64
|
+
*/
|
|
65
|
+
export function getMinRangeFromZoom(zoom) {
|
|
66
|
+
// 每个瓦片覆盖的经度范围
|
|
67
|
+
const lonPerTile = 360 / Math.pow(2, zoom);
|
|
68
|
+
// 每个瓦片覆盖的纬度范围(近似)
|
|
69
|
+
const latPerTile = 180 / Math.pow(2, zoom);
|
|
70
|
+
|
|
71
|
+
// 返回一个足够小的范围,比如一个瓦片范围的一半
|
|
72
|
+
return Math.max(lonPerTile, latPerTile) / 2;
|
|
73
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 通用函数:提取所有坐标并扁平化为普通数组
|
|
3
|
+
* @param geojsonFeature
|
|
4
|
+
* @param geomType
|
|
5
|
+
* @returns
|
|
6
|
+
*/
|
|
7
|
+
export function extractCoordinatesToArr(coords, geomType) {
|
|
8
|
+
if (geomType === "Polygon") {
|
|
9
|
+
// 多边形:三维数组 [环1[点1,点2...], 环2[...]] -> 转为二维数组
|
|
10
|
+
return coords.map(
|
|
11
|
+
(ring) => ring.map((coord) => [coord[0], coord[1]]), // 提取经度、纬度
|
|
12
|
+
);
|
|
13
|
+
} else if (geomType === "MultiPolygon") {
|
|
14
|
+
// 多部件多边形:四维数组 -> 转为三维数组
|
|
15
|
+
return coords.map((polygon) => polygon.map((ring) => ring.map((coord) => [coord[0], coord[1]])));
|
|
16
|
+
} else if (geomType === "Point") {
|
|
17
|
+
// 点:返回一维数组
|
|
18
|
+
return [coords[0], coords[1]];
|
|
19
|
+
} else if (geomType === "LineString") {
|
|
20
|
+
// 线:返回二维数组
|
|
21
|
+
return coords.map((coord) => [coord[0], coord[1]]);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return coords;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 通用函数:提取所有坐标并扁平化为普通数组
|
|
29
|
+
* @param geojsonFeature
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
export function extractGeojsonCoordinatesToArr(geojsonFeature) {
|
|
33
|
+
const coords = geojsonFeature.geometry.coordinates;
|
|
34
|
+
const geomType = geojsonFeature.geometry.type;
|
|
35
|
+
if (geomType === "Polygon") {
|
|
36
|
+
// 多边形:三维数组 [环1[点1,点2...], 环2[...]] -> 转为二维数组
|
|
37
|
+
return coords.map(
|
|
38
|
+
(ring) => ring.map((coord) => [coord[0], coord[1]]), // 提取经度、纬度
|
|
39
|
+
);
|
|
40
|
+
} else if (geomType === "MultiPolygon") {
|
|
41
|
+
// 多部件多边形:四维数组 -> 转为三维数组
|
|
42
|
+
return coords.map((polygon) => polygon.map((ring) => ring.map((coord) => [coord[0], coord[1]])));
|
|
43
|
+
} else if (geomType === "Point") {
|
|
44
|
+
// 点:返回一维数组
|
|
45
|
+
return [coords[0], coords[1]];
|
|
46
|
+
} else if (geomType === "LineString") {
|
|
47
|
+
// 线:返回二维数组
|
|
48
|
+
return coords.map((coord) => [coord[0], coord[1]]);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return coords;
|
|
52
|
+
}
|