@movk/maplibre 1.0.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/LICENSE +21 -0
- package/README.en.md +192 -0
- package/README.md +191 -0
- package/dist/module.d.mts +20 -0
- package/dist/module.d.ts +20 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +63 -0
- package/dist/runtime/components/CustomLayer.d.vue.ts +24 -0
- package/dist/runtime/components/CustomLayer.vue +23 -0
- package/dist/runtime/components/CustomLayer.vue.d.ts +24 -0
- package/dist/runtime/components/Layer.d.vue.ts +75 -0
- package/dist/runtime/components/Layer.vue +112 -0
- package/dist/runtime/components/Layer.vue.d.ts +75 -0
- package/dist/runtime/components/LayerGroup.d.vue.ts +25 -0
- package/dist/runtime/components/LayerGroup.vue +16 -0
- package/dist/runtime/components/LayerGroup.vue.d.ts +25 -0
- package/dist/runtime/components/LottieMarker.d.vue.ts +50 -0
- package/dist/runtime/components/LottieMarker.vue +31 -0
- package/dist/runtime/components/LottieMarker.vue.d.ts +50 -0
- package/dist/runtime/components/Map.d.vue.ts +84 -0
- package/dist/runtime/components/Map.vue +134 -0
- package/dist/runtime/components/Map.vue.d.ts +84 -0
- package/dist/runtime/components/Marker.d.vue.ts +54 -0
- package/dist/runtime/components/Marker.vue +86 -0
- package/dist/runtime/components/Marker.vue.d.ts +54 -0
- package/dist/runtime/components/Popup.d.vue.ts +30 -0
- package/dist/runtime/components/Popup.vue +33 -0
- package/dist/runtime/components/Popup.vue.d.ts +30 -0
- package/dist/runtime/components/Source.d.vue.ts +23 -0
- package/dist/runtime/components/Source.vue +44 -0
- package/dist/runtime/components/Source.vue.d.ts +23 -0
- package/dist/runtime/components/Tooltip.d.vue.ts +45 -0
- package/dist/runtime/components/Tooltip.vue +106 -0
- package/dist/runtime/components/Tooltip.vue.d.ts +45 -0
- package/dist/runtime/components/buffers/BufferCircle.d.vue.ts +27 -0
- package/dist/runtime/components/buffers/BufferCircle.vue +30 -0
- package/dist/runtime/components/buffers/BufferCircle.vue.d.ts +27 -0
- package/dist/runtime/components/buffers/BufferEllipse.d.vue.ts +35 -0
- package/dist/runtime/components/buffers/BufferEllipse.vue +36 -0
- package/dist/runtime/components/buffers/BufferEllipse.vue.d.ts +35 -0
- package/dist/runtime/components/buffers/BufferLine.d.vue.ts +21 -0
- package/dist/runtime/components/buffers/BufferLine.vue +40 -0
- package/dist/runtime/components/buffers/BufferLine.vue.d.ts +21 -0
- package/dist/runtime/components/buffers/BufferPolygon.d.vue.ts +21 -0
- package/dist/runtime/components/buffers/BufferPolygon.vue +40 -0
- package/dist/runtime/components/buffers/BufferPolygon.vue.d.ts +21 -0
- package/dist/runtime/components/buffers/BufferSector.d.vue.ts +31 -0
- package/dist/runtime/components/buffers/BufferSector.vue +35 -0
- package/dist/runtime/components/buffers/BufferSector.vue.d.ts +31 -0
- package/dist/runtime/components/controls/AttributionControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/AttributionControl.vue +18 -0
- package/dist/runtime/components/controls/AttributionControl.vue.d.ts +24 -0
- package/dist/runtime/components/controls/FullscreenControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/FullscreenControl.vue +18 -0
- package/dist/runtime/components/controls/FullscreenControl.vue.d.ts +24 -0
- package/dist/runtime/components/controls/GeolocateControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/GeolocateControl.vue +18 -0
- package/dist/runtime/components/controls/GeolocateControl.vue.d.ts +24 -0
- package/dist/runtime/components/controls/NavigationControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/NavigationControl.vue +18 -0
- package/dist/runtime/components/controls/NavigationControl.vue.d.ts +24 -0
- package/dist/runtime/components/controls/ScaleControl.d.vue.ts +24 -0
- package/dist/runtime/components/controls/ScaleControl.vue +18 -0
- package/dist/runtime/components/controls/ScaleControl.vue.d.ts +24 -0
- package/dist/runtime/components/effects/AnimatedImage.d.vue.ts +28 -0
- package/dist/runtime/components/effects/AnimatedImage.vue +50 -0
- package/dist/runtime/components/effects/AnimatedImage.vue.d.ts +28 -0
- package/dist/runtime/components/effects/DiffusionCircle.d.vue.ts +44 -0
- package/dist/runtime/components/effects/DiffusionCircle.vue +47 -0
- package/dist/runtime/components/effects/DiffusionCircle.vue.d.ts +44 -0
- package/dist/runtime/components/effects/FlowBuilding.d.vue.ts +53 -0
- package/dist/runtime/components/effects/FlowBuilding.vue +64 -0
- package/dist/runtime/components/effects/FlowBuilding.vue.d.ts +53 -0
- package/dist/runtime/components/effects/GlowCircle.d.vue.ts +44 -0
- package/dist/runtime/components/effects/GlowCircle.vue +42 -0
- package/dist/runtime/components/effects/GlowCircle.vue.d.ts +44 -0
- package/dist/runtime/components/effects/GradientBuilding.d.vue.ts +25 -0
- package/dist/runtime/components/effects/GradientBuilding.vue +37 -0
- package/dist/runtime/components/effects/GradientBuilding.vue.d.ts +25 -0
- package/dist/runtime/components/effects/Migration.d.vue.ts +50 -0
- package/dist/runtime/components/effects/Migration.vue +90 -0
- package/dist/runtime/components/effects/Migration.vue.d.ts +50 -0
- package/dist/runtime/components/effects/Radar.d.vue.ts +32 -0
- package/dist/runtime/components/effects/Radar.vue +49 -0
- package/dist/runtime/components/effects/Radar.vue.d.ts +32 -0
- package/dist/runtime/components/effects/SpriteImage.d.vue.ts +41 -0
- package/dist/runtime/components/effects/SpriteImage.vue +67 -0
- package/dist/runtime/components/effects/SpriteImage.vue.d.ts +41 -0
- package/dist/runtime/components/effects/TextureBuilding.d.vue.ts +25 -0
- package/dist/runtime/components/effects/TextureBuilding.vue +39 -0
- package/dist/runtime/components/effects/TextureBuilding.vue.d.ts +25 -0
- package/dist/runtime/components/effects/Trail.d.vue.ts +44 -0
- package/dist/runtime/components/effects/Trail.vue +61 -0
- package/dist/runtime/components/effects/Trail.vue.d.ts +44 -0
- package/dist/runtime/components/effects/WaveCircle.d.vue.ts +44 -0
- package/dist/runtime/components/effects/WaveCircle.vue +55 -0
- package/dist/runtime/components/effects/WaveCircle.vue.d.ts +44 -0
- package/dist/runtime/components/effects/WindowBuilding.d.vue.ts +53 -0
- package/dist/runtime/components/effects/WindowBuilding.vue +61 -0
- package/dist/runtime/components/effects/WindowBuilding.vue.d.ts +53 -0
- package/dist/runtime/components/environment/Sky.d.vue.ts +21 -0
- package/dist/runtime/components/environment/Sky.vue +15 -0
- package/dist/runtime/components/environment/Sky.vue.d.ts +21 -0
- package/dist/runtime/components/environment/Temperature.d.vue.ts +47 -0
- package/dist/runtime/components/environment/Temperature.vue +41 -0
- package/dist/runtime/components/environment/Temperature.vue.d.ts +47 -0
- package/dist/runtime/components/environment/Terrain.d.vue.ts +34 -0
- package/dist/runtime/components/environment/Terrain.vue +47 -0
- package/dist/runtime/components/environment/Terrain.vue.d.ts +34 -0
- package/dist/runtime/components/extensions/DrawControl.d.vue.ts +0 -0
- package/dist/runtime/components/extensions/DrawControl.vue +168 -0
- package/dist/runtime/components/extensions/DrawControl.vue.d.ts +0 -0
- package/dist/runtime/components/extensions/TiandituLayer.d.vue.ts +20 -0
- package/dist/runtime/components/extensions/TiandituLayer.vue +26 -0
- package/dist/runtime/components/extensions/TiandituLayer.vue.d.ts +20 -0
- package/dist/runtime/components/extensions/WmsLayer.d.vue.ts +50 -0
- package/dist/runtime/components/extensions/WmsLayer.vue +39 -0
- package/dist/runtime/components/extensions/WmsLayer.vue.d.ts +50 -0
- package/dist/runtime/components/extensions/WmtsLayer.d.vue.ts +42 -0
- package/dist/runtime/components/extensions/WmtsLayer.vue +37 -0
- package/dist/runtime/components/extensions/WmtsLayer.vue.d.ts +42 -0
- package/dist/runtime/components/layers/BuildingLayer.d.vue.ts +28 -0
- package/dist/runtime/components/layers/BuildingLayer.vue +41 -0
- package/dist/runtime/components/layers/BuildingLayer.vue.d.ts +28 -0
- package/dist/runtime/components/layers/ClusterLayer.d.vue.ts +55 -0
- package/dist/runtime/components/layers/ClusterLayer.vue +86 -0
- package/dist/runtime/components/layers/ClusterLayer.vue.d.ts +55 -0
- package/dist/runtime/components/layers/ImageLayer.d.vue.ts +21 -0
- package/dist/runtime/components/layers/ImageLayer.vue +25 -0
- package/dist/runtime/components/layers/ImageLayer.vue.d.ts +21 -0
- package/dist/runtime/components/layers/RasterLayer.d.vue.ts +35 -0
- package/dist/runtime/components/layers/RasterLayer.vue +34 -0
- package/dist/runtime/components/layers/RasterLayer.vue.d.ts +35 -0
- package/dist/runtime/components/layers/VideoLayer.d.vue.ts +28 -0
- package/dist/runtime/components/layers/VideoLayer.vue +38 -0
- package/dist/runtime/components/layers/VideoLayer.vue.d.ts +28 -0
- package/dist/runtime/composables/defineMaplibreControl.d.ts +3 -0
- package/dist/runtime/composables/defineMaplibreControl.js +6 -0
- package/dist/runtime/composables/useFeatureState.d.ts +35 -0
- package/dist/runtime/composables/useFeatureState.js +76 -0
- package/dist/runtime/composables/useFrameIcon.d.ts +17 -0
- package/dist/runtime/composables/useFrameIcon.js +36 -0
- package/dist/runtime/composables/useMap.d.ts +3 -0
- package/dist/runtime/composables/useMap.js +9 -0
- package/dist/runtime/composables/useMapAnimation.d.ts +21 -0
- package/dist/runtime/composables/useMapAnimation.js +13 -0
- package/dist/runtime/composables/useMapExport.d.ts +34 -0
- package/dist/runtime/composables/useMapExport.js +35 -0
- package/dist/runtime/composables/useMaplibre.d.ts +6 -0
- package/dist/runtime/composables/useMaplibre.js +4 -0
- package/dist/runtime/composables/useMaplibreCamera.d.ts +15 -0
- package/dist/runtime/composables/useMaplibreCamera.js +32 -0
- package/dist/runtime/composables/useMaplibreDraw.d.ts +10 -0
- package/dist/runtime/composables/useMaplibreDraw.js +34 -0
- package/dist/runtime/composables/useMaplibreImage.d.ts +19 -0
- package/dist/runtime/composables/useMaplibreImage.js +33 -0
- package/dist/runtime/composables/useMeasure.d.ts +25 -0
- package/dist/runtime/composables/useMeasure.js +173 -0
- package/dist/runtime/domains/map/config.d.ts +7 -0
- package/dist/runtime/domains/map/config.js +13 -0
- package/dist/runtime/domains/map/context.d.ts +13 -0
- package/dist/runtime/domains/map/context.js +51 -0
- package/dist/runtime/domains/map/control.d.ts +4 -0
- package/dist/runtime/domains/map/control.js +28 -0
- package/dist/runtime/domains/map/create-map.d.ts +3 -0
- package/dist/runtime/domains/map/create-map.js +21 -0
- package/dist/runtime/domains/map/draw-context.d.ts +26 -0
- package/dist/runtime/domains/map/draw-context.js +73 -0
- package/dist/runtime/domains/map/draw-registry.d.ts +5 -0
- package/dist/runtime/domains/map/draw-registry.js +15 -0
- package/dist/runtime/domains/map/draw-toolbar.d.ts +15 -0
- package/dist/runtime/domains/map/draw-toolbar.js +52 -0
- package/dist/runtime/domains/map/draw.d.ts +4 -0
- package/dist/runtime/domains/map/draw.js +1 -0
- package/dist/runtime/domains/map/layer-group.d.ts +9 -0
- package/dist/runtime/domains/map/layer-group.js +1 -0
- package/dist/runtime/domains/map/registry.d.ts +4 -0
- package/dist/runtime/domains/map/registry.js +10 -0
- package/dist/runtime/domains/map/resolve.d.ts +7 -0
- package/dist/runtime/domains/map/resolve.js +7 -0
- package/dist/runtime/domains/map/style-effect.d.ts +6 -0
- package/dist/runtime/domains/map/style-effect.js +21 -0
- package/dist/runtime/draw-modes/index.d.ts +16 -0
- package/dist/runtime/draw-modes/index.js +32 -0
- package/dist/runtime/index.css +1 -0
- package/dist/runtime/plugins/config.d.ts +2 -0
- package/dist/runtime/plugins/config.js +6 -0
- package/dist/runtime/types/draw.d.ts +30 -0
- package/dist/runtime/types/draw.js +0 -0
- package/dist/runtime/types/index.d.ts +3 -0
- package/dist/runtime/types/index.js +0 -0
- package/dist/runtime/types/map.d.ts +45 -0
- package/dist/runtime/types/map.js +0 -0
- package/dist/runtime/types/tianditu.d.ts +247 -0
- package/dist/runtime/types/tianditu.js +0 -0
- package/dist/runtime/utils/animated-image.d.ts +13 -0
- package/dist/runtime/utils/animated-image.js +47 -0
- package/dist/runtime/utils/buffer.d.ts +24 -0
- package/dist/runtime/utils/buffer.js +13 -0
- package/dist/runtime/utils/building-effects.d.ts +73 -0
- package/dist/runtime/utils/building-effects.js +50 -0
- package/dist/runtime/utils/building.d.ts +53 -0
- package/dist/runtime/utils/building.js +26 -0
- package/dist/runtime/utils/cluster.d.ts +24 -0
- package/dist/runtime/utils/cluster.js +42 -0
- package/dist/runtime/utils/coordinate.d.ts +12 -0
- package/dist/runtime/utils/coordinate.js +44 -0
- package/dist/runtime/utils/draw-theme.d.ts +47 -0
- package/dist/runtime/utils/draw-theme.js +39 -0
- package/dist/runtime/utils/effects.d.ts +34 -0
- package/dist/runtime/utils/effects.js +78 -0
- package/dist/runtime/utils/events.d.ts +6 -0
- package/dist/runtime/utils/events.js +20 -0
- package/dist/runtime/utils/frame-icon.d.ts +27 -0
- package/dist/runtime/utils/frame-icon.js +45 -0
- package/dist/runtime/utils/geometry.d.ts +5 -0
- package/dist/runtime/utils/geometry.js +41 -0
- package/dist/runtime/utils/heatmap.d.ts +36 -0
- package/dist/runtime/utils/heatmap.js +30 -0
- package/dist/runtime/utils/layer.d.ts +13 -0
- package/dist/runtime/utils/layer.js +17 -0
- package/dist/runtime/utils/logger.d.ts +2 -0
- package/dist/runtime/utils/logger.js +2 -0
- package/dist/runtime/utils/measure.d.ts +4 -0
- package/dist/runtime/utils/measure.js +8 -0
- package/dist/runtime/utils/sprite.d.ts +31 -0
- package/dist/runtime/utils/sprite.js +23 -0
- package/dist/runtime/utils/tianditu-administrative.d.ts +3 -0
- package/dist/runtime/utils/tianditu-administrative.js +48 -0
- package/dist/runtime/utils/tianditu-client.d.ts +30 -0
- package/dist/runtime/utils/tianditu-client.js +17 -0
- package/dist/runtime/utils/tianditu-geocoder.d.ts +5 -0
- package/dist/runtime/utils/tianditu-geocoder.js +37 -0
- package/dist/runtime/utils/tianditu-request.d.ts +20 -0
- package/dist/runtime/utils/tianditu-request.js +42 -0
- package/dist/runtime/utils/tianditu-route.d.ts +3 -0
- package/dist/runtime/utils/tianditu-route.js +40 -0
- package/dist/runtime/utils/tianditu-search.d.ts +15 -0
- package/dist/runtime/utils/tianditu-search.js +183 -0
- package/dist/runtime/utils/tianditu.d.ts +21 -0
- package/dist/runtime/utils/tianditu.js +26 -0
- package/dist/runtime/utils/wms.d.ts +43 -0
- package/dist/runtime/utils/wms.js +30 -0
- package/dist/runtime/utils/wmts.d.ts +35 -0
- package/dist/runtime/utils/wmts.js +29 -0
- package/dist/types.d.mts +5 -0
- package/dist/unplugin.d.mts +30 -0
- package/dist/unplugin.d.ts +30 -0
- package/dist/unplugin.mjs +53 -0
- package/dist/vite.d.mts +7 -0
- package/dist/vite.d.ts +7 -0
- package/dist/vite.mjs +11 -0
- package/dist/vue-plugin.d.mts +9 -0
- package/dist/vue-plugin.d.ts +9 -0
- package/dist/vue-plugin.mjs +9 -0
- package/package.json +174 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { onUnmounted, ref } from "vue";
|
|
2
|
+
import { length } from "@turf/length";
|
|
3
|
+
import { area } from "@turf/area";
|
|
4
|
+
import { useContextResolver } from "../domains/map/resolve.js";
|
|
5
|
+
import { formatArea, formatDistance } from "../utils/measure.js";
|
|
6
|
+
import { logger } from "../utils/logger.js";
|
|
7
|
+
import { textFontLayout } from "../domains/map/config.js";
|
|
8
|
+
const SOURCE_ID = "movk-measure";
|
|
9
|
+
export function useMeasure(options = {}) {
|
|
10
|
+
const color = options.color ?? "#f59e0b";
|
|
11
|
+
const resolve = useContextResolver(options.mapId);
|
|
12
|
+
const mode = ref();
|
|
13
|
+
const active = ref(false);
|
|
14
|
+
const result = ref("");
|
|
15
|
+
let finished = [];
|
|
16
|
+
let vertices = [];
|
|
17
|
+
let cursor;
|
|
18
|
+
let boundMap;
|
|
19
|
+
let stopReady;
|
|
20
|
+
function isAlive(map) {
|
|
21
|
+
return Boolean(map.getCanvas());
|
|
22
|
+
}
|
|
23
|
+
function setCursor(map, value) {
|
|
24
|
+
const canvas = map.getCanvas();
|
|
25
|
+
if (canvas) canvas.style.cursor = value;
|
|
26
|
+
}
|
|
27
|
+
function ensureLayers(map) {
|
|
28
|
+
if (!map.getSource(SOURCE_ID)) {
|
|
29
|
+
map.addSource(SOURCE_ID, { type: "geojson", data: collection() });
|
|
30
|
+
}
|
|
31
|
+
const layers = [
|
|
32
|
+
{ id: `${SOURCE_ID}-fill`, type: "fill", filter: ["==", ["geometry-type"], "Polygon"], paint: { "fill-color": color, "fill-opacity": 0.15 } },
|
|
33
|
+
{ id: `${SOURCE_ID}-line`, type: "line", filter: ["!=", ["geometry-type"], "Point"], paint: { "line-color": color, "line-width": 2, "line-dasharray": [2, 1] } },
|
|
34
|
+
{ id: `${SOURCE_ID}-points`, type: "circle", filter: ["==", ["geometry-type"], "Point"], paint: { "circle-radius": 4, "circle-color": "#fff", "circle-stroke-color": color, "circle-stroke-width": 2 } },
|
|
35
|
+
{ id: `${SOURCE_ID}-labels`, type: "symbol", filter: ["has", "label"], layout: { "text-field": ["get", "label"], "text-size": 13, "text-offset": [0, -1.2], "text-anchor": "bottom", ...textFontLayout() }, paint: { "text-color": color, "text-halo-color": "#fff", "text-halo-width": 1.5 } }
|
|
36
|
+
];
|
|
37
|
+
for (const layer of layers) {
|
|
38
|
+
if (!map.getLayer(layer.id)) map.addLayer({ source: SOURCE_ID, ...layer });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function currentFeature() {
|
|
42
|
+
const coords = cursor ? [...vertices, cursor] : [...vertices];
|
|
43
|
+
if (mode.value === "area") {
|
|
44
|
+
if (coords.length < 3) return void 0;
|
|
45
|
+
return { type: "Feature", properties: {}, geometry: { type: "Polygon", coordinates: [[...coords, coords[0]]] } };
|
|
46
|
+
}
|
|
47
|
+
if (coords.length < 2) return void 0;
|
|
48
|
+
return { type: "Feature", properties: {}, geometry: { type: "LineString", coordinates: coords } };
|
|
49
|
+
}
|
|
50
|
+
function measureOf(feature) {
|
|
51
|
+
return feature.geometry.type === "Polygon" ? formatArea(area(feature)) : formatDistance(length(feature, { units: "kilometers" }) * 1e3);
|
|
52
|
+
}
|
|
53
|
+
function collection() {
|
|
54
|
+
const features = [...finished];
|
|
55
|
+
const current = currentFeature();
|
|
56
|
+
if (current) features.push(current);
|
|
57
|
+
for (const vertex of vertices) {
|
|
58
|
+
features.push({ type: "Feature", properties: {}, geometry: { type: "Point", coordinates: vertex } });
|
|
59
|
+
}
|
|
60
|
+
return { type: "FeatureCollection", features };
|
|
61
|
+
}
|
|
62
|
+
function refresh() {
|
|
63
|
+
const map = boundMap;
|
|
64
|
+
if (!map || !isAlive(map)) return;
|
|
65
|
+
const source = map.getSource(SOURCE_ID);
|
|
66
|
+
source?.setData(collection());
|
|
67
|
+
const current = currentFeature();
|
|
68
|
+
result.value = current ? measureOf(current) : "";
|
|
69
|
+
}
|
|
70
|
+
function onClick(event) {
|
|
71
|
+
vertices = [...vertices, [event.lngLat.lng, event.lngLat.lat]];
|
|
72
|
+
refresh();
|
|
73
|
+
}
|
|
74
|
+
function onMove(event) {
|
|
75
|
+
if (!vertices.length) return;
|
|
76
|
+
cursor = [event.lngLat.lng, event.lngLat.lat];
|
|
77
|
+
refresh();
|
|
78
|
+
}
|
|
79
|
+
function finishSegment() {
|
|
80
|
+
cursor = void 0;
|
|
81
|
+
const current = currentFeature();
|
|
82
|
+
if (current) {
|
|
83
|
+
const label = measureOf(current);
|
|
84
|
+
const anchor = vertices[vertices.length - 1];
|
|
85
|
+
finished = [
|
|
86
|
+
...finished,
|
|
87
|
+
current,
|
|
88
|
+
{ type: "Feature", properties: { label }, geometry: { type: "Point", coordinates: anchor } }
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
vertices = [];
|
|
92
|
+
refresh();
|
|
93
|
+
}
|
|
94
|
+
function onDblClick(event) {
|
|
95
|
+
event.preventDefault();
|
|
96
|
+
vertices = vertices.slice(0, -1);
|
|
97
|
+
finishSegment();
|
|
98
|
+
}
|
|
99
|
+
function onKeydown(event) {
|
|
100
|
+
if (event.key !== "Escape") return;
|
|
101
|
+
vertices = [];
|
|
102
|
+
cursor = void 0;
|
|
103
|
+
refresh();
|
|
104
|
+
}
|
|
105
|
+
function start(nextMode) {
|
|
106
|
+
const ctx = resolve();
|
|
107
|
+
if (!ctx) {
|
|
108
|
+
logger.warn("useMeasure: no map context found; pass options.mapId or call inside <MaplibreMap>.");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (active.value) stop();
|
|
112
|
+
mode.value = nextMode;
|
|
113
|
+
active.value = true;
|
|
114
|
+
stopReady = ctx.onReady((map) => {
|
|
115
|
+
boundMap = map;
|
|
116
|
+
ensureLayers(map);
|
|
117
|
+
refresh();
|
|
118
|
+
});
|
|
119
|
+
void ctx.whenLoaded().then((map) => {
|
|
120
|
+
if (!active.value) return;
|
|
121
|
+
map.doubleClickZoom.disable();
|
|
122
|
+
setCursor(map, "crosshair");
|
|
123
|
+
map.on("click", onClick);
|
|
124
|
+
map.on("mousemove", onMove);
|
|
125
|
+
map.on("dblclick", onDblClick);
|
|
126
|
+
window.addEventListener("keydown", onKeydown);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function stop() {
|
|
130
|
+
if (!active.value) return;
|
|
131
|
+
active.value = false;
|
|
132
|
+
vertices = [];
|
|
133
|
+
cursor = void 0;
|
|
134
|
+
stopReady?.();
|
|
135
|
+
stopReady = void 0;
|
|
136
|
+
const map = boundMap;
|
|
137
|
+
if (map) {
|
|
138
|
+
map.off("click", onClick);
|
|
139
|
+
map.off("mousemove", onMove);
|
|
140
|
+
map.off("dblclick", onDblClick);
|
|
141
|
+
map.doubleClickZoom.enable();
|
|
142
|
+
setCursor(map, "");
|
|
143
|
+
refresh();
|
|
144
|
+
}
|
|
145
|
+
window.removeEventListener("keydown", onKeydown);
|
|
146
|
+
result.value = "";
|
|
147
|
+
}
|
|
148
|
+
function clear() {
|
|
149
|
+
finished = [];
|
|
150
|
+
vertices = [];
|
|
151
|
+
cursor = void 0;
|
|
152
|
+
refresh();
|
|
153
|
+
}
|
|
154
|
+
function teardown() {
|
|
155
|
+
stop();
|
|
156
|
+
const map = boundMap;
|
|
157
|
+
if (!map || !isAlive(map)) {
|
|
158
|
+
boundMap = void 0;
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
for (const suffix of ["-fill", "-line", "-points", "-labels"]) {
|
|
162
|
+
const layerId = `${SOURCE_ID}${suffix}`;
|
|
163
|
+
if (map.getLayer(layerId)) map.removeLayer(layerId);
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
if (map.getSource(SOURCE_ID)) map.removeSource(SOURCE_ID);
|
|
167
|
+
} catch {
|
|
168
|
+
}
|
|
169
|
+
boundMap = void 0;
|
|
170
|
+
}
|
|
171
|
+
onUnmounted(teardown);
|
|
172
|
+
return { start, stop, clear, mode, active, result };
|
|
173
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MaplibreRuntimeConfig } from '../../types';
|
|
2
|
+
export declare function setMaplibreConfig(value: Partial<MaplibreRuntimeConfig>): void;
|
|
3
|
+
export declare function getMaplibreConfig(): MaplibreRuntimeConfig;
|
|
4
|
+
/** 库内置文字图层的 layout 字体片段:配置了 textFont 才输出,否则交由样式默认 */
|
|
5
|
+
export declare function textFontLayout(): {
|
|
6
|
+
'text-font'?: string[];
|
|
7
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const STORE_KEY = Symbol.for("movk-maplibre:config");
|
|
2
|
+
const globalScope = globalThis;
|
|
3
|
+
const store = globalScope[STORE_KEY] ??= { config: {} };
|
|
4
|
+
export function setMaplibreConfig(value) {
|
|
5
|
+
store.config = { ...store.config, ...value };
|
|
6
|
+
}
|
|
7
|
+
export function getMaplibreConfig() {
|
|
8
|
+
return store.config;
|
|
9
|
+
}
|
|
10
|
+
export function textFontLayout() {
|
|
11
|
+
const { textFont } = store.config;
|
|
12
|
+
return textFont ? { "text-font": textFont } : {};
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InjectionKey } from 'vue';
|
|
2
|
+
import type { Map as MaplibreMap } from 'maplibre-gl';
|
|
3
|
+
import type { MaplibreContext } from '../../types';
|
|
4
|
+
/** MaplibreMap 向子组件下发上下文的注入键 */
|
|
5
|
+
export declare const MaplibreContextKey: InjectionKey<MaplibreContext>;
|
|
6
|
+
/**
|
|
7
|
+
* 创建上下文骨架(map 初始为 undefined),供 setup 阶段同步 provide。
|
|
8
|
+
* 实例就绪后由返回的 attach 挂载,避免把 provide 推迟到 onMounted。
|
|
9
|
+
*/
|
|
10
|
+
export declare function createMaplibreContext(id: string): {
|
|
11
|
+
context: MaplibreContext;
|
|
12
|
+
attach: (map: MaplibreMap) => void;
|
|
13
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ref, shallowRef } from "vue";
|
|
2
|
+
export const MaplibreContextKey = Symbol("movk-maplibre:context");
|
|
3
|
+
export function createMaplibreContext(id) {
|
|
4
|
+
const map = shallowRef();
|
|
5
|
+
const isLoaded = ref(false);
|
|
6
|
+
const readyCallbacks = /* @__PURE__ */ new Set();
|
|
7
|
+
let resolveLoaded;
|
|
8
|
+
const loadedPromise = new Promise((resolve) => {
|
|
9
|
+
resolveLoaded = resolve;
|
|
10
|
+
});
|
|
11
|
+
function attach(instance) {
|
|
12
|
+
map.value = instance;
|
|
13
|
+
instance.on("load", () => {
|
|
14
|
+
isLoaded.value = true;
|
|
15
|
+
resolveLoaded(instance);
|
|
16
|
+
});
|
|
17
|
+
instance.on("style.load", () => {
|
|
18
|
+
for (const callback of readyCallbacks) callback(instance);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const context = {
|
|
22
|
+
id,
|
|
23
|
+
map,
|
|
24
|
+
isLoaded,
|
|
25
|
+
whenLoaded: () => loadedPromise,
|
|
26
|
+
onReady(callback) {
|
|
27
|
+
readyCallbacks.add(callback);
|
|
28
|
+
const unregister = () => readyCallbacks.delete(callback);
|
|
29
|
+
const instance = map.value;
|
|
30
|
+
if (!instance) {
|
|
31
|
+
return unregister;
|
|
32
|
+
}
|
|
33
|
+
if (instance.isStyleLoaded()) {
|
|
34
|
+
callback(instance);
|
|
35
|
+
return unregister;
|
|
36
|
+
}
|
|
37
|
+
const events = ["styledata", "sourcedata", "idle"];
|
|
38
|
+
const onData = () => {
|
|
39
|
+
if (!instance.isStyleLoaded()) return;
|
|
40
|
+
for (const e of events) instance.off(e, onData);
|
|
41
|
+
if (readyCallbacks.has(callback)) callback(instance);
|
|
42
|
+
};
|
|
43
|
+
for (const e of events) instance.on(e, onData);
|
|
44
|
+
return () => {
|
|
45
|
+
unregister();
|
|
46
|
+
for (const e of events) instance.off(e, onData);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
return { context, attach };
|
|
51
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MaybeRefOrGetter } from 'vue';
|
|
2
|
+
import type { ControlPosition, IControl } from 'maplibre-gl';
|
|
3
|
+
/** 控件组件共享逻辑:地图就绪后 addControl;position/options 变化时移除并按新配置重建;卸载时 removeControl。 */
|
|
4
|
+
export declare function useControl(create: () => IControl, position?: MaybeRefOrGetter<ControlPosition | undefined>, watchSource?: () => unknown): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { onMounted, onUnmounted, toValue, watch } from "vue";
|
|
2
|
+
import { useMap } from "../../composables/useMap.js";
|
|
3
|
+
export function useControl(create, position, watchSource) {
|
|
4
|
+
const ctx = useMap();
|
|
5
|
+
let control;
|
|
6
|
+
function rebuild() {
|
|
7
|
+
const map = ctx.map.value;
|
|
8
|
+
if (!map) return;
|
|
9
|
+
if (control) map.removeControl(control);
|
|
10
|
+
control = create();
|
|
11
|
+
map.addControl(control, toValue(position));
|
|
12
|
+
}
|
|
13
|
+
onMounted(async () => {
|
|
14
|
+
await ctx.whenLoaded();
|
|
15
|
+
rebuild();
|
|
16
|
+
});
|
|
17
|
+
watch(
|
|
18
|
+
() => [toValue(position), watchSource?.()],
|
|
19
|
+
() => {
|
|
20
|
+
if (control) rebuild();
|
|
21
|
+
},
|
|
22
|
+
{ deep: true }
|
|
23
|
+
);
|
|
24
|
+
onUnmounted(() => {
|
|
25
|
+
if (control) ctx.map.value?.removeControl(control);
|
|
26
|
+
control = void 0;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Map as MaplibreGlMap, prewarm, setRTLTextPlugin, setWorkerCount, setWorkerUrl } from "maplibre-gl";
|
|
2
|
+
import { logger } from "../../utils/logger.js";
|
|
3
|
+
import { getMaplibreConfig } from "./config.js";
|
|
4
|
+
const DEFAULT_RTL_PLUGIN = "https://cdn.jsdelivr.net/npm/@mapbox/mapbox-gl-rtl-text@0.3.0/dist/mapbox-gl-rtl-text.js";
|
|
5
|
+
let globalConfigApplied = false;
|
|
6
|
+
function applyGlobalConfig() {
|
|
7
|
+
if (globalConfigApplied) return;
|
|
8
|
+
globalConfigApplied = true;
|
|
9
|
+
const config = getMaplibreConfig();
|
|
10
|
+
if (config.workerUrl) setWorkerUrl(config.workerUrl);
|
|
11
|
+
if (config.workerCount) setWorkerCount(config.workerCount);
|
|
12
|
+
if (config.prewarm) prewarm();
|
|
13
|
+
if (config.RTLTextPlugin) {
|
|
14
|
+
const plugin = typeof config.RTLTextPlugin === "boolean" ? {} : config.RTLTextPlugin;
|
|
15
|
+
setRTLTextPlugin(plugin.pluginURL || DEFAULT_RTL_PLUGIN, plugin.lazy ?? false).catch((error) => logger.warn("Failed to load RTL text plugin", error));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function createMaplibreGl(options) {
|
|
19
|
+
applyGlobalConfig();
|
|
20
|
+
return new MaplibreGlMap(options);
|
|
21
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { GeoJSONStoreFeatures, TerraDraw, TerraDrawExtend } from 'terra-draw';
|
|
2
|
+
import type { Feature, FeatureCollection, Geometry } from 'geojson';
|
|
3
|
+
import type { MaplibreDrawContext } from '../../types';
|
|
4
|
+
type FeatureId = TerraDrawExtend.FeatureId;
|
|
5
|
+
/** 控件把受控模型的回写通道交给上下文,绘制指令与模型同步因此只有一处实现 */
|
|
6
|
+
export interface DrawContextCallbacks {
|
|
7
|
+
/** 要素集合变更后回写 v-model:features */
|
|
8
|
+
onFeatures: (features: Feature[]) => void;
|
|
9
|
+
/** 模式变更后回写 v-model:mode */
|
|
10
|
+
onMode: (mode: string) => void;
|
|
11
|
+
}
|
|
12
|
+
/** 已完成的要素:排除绘制中的要素与编辑辅助点 */
|
|
13
|
+
export declare function committedFeatures(draw: TerraDraw): GeoJSONStoreFeatures[];
|
|
14
|
+
/** 规范化为 terra-draw store 要素:补 id 与 mode,跳过不支持的几何 */
|
|
15
|
+
export declare function toStoreFeatures(draw: TerraDraw, geojson: Feature | FeatureCollection | Geometry): GeoJSONStoreFeatures[];
|
|
16
|
+
/** 添加要素并返回通过校验的 id,未通过的逐个告警 */
|
|
17
|
+
export declare function addStoreFeatures(draw: TerraDraw, features: GeoJSONStoreFeatures[]): FeatureId[];
|
|
18
|
+
/**
|
|
19
|
+
* 创建绘制上下文骨架(draw 初始为 undefined),供 setup 阶段同步 provide 与注册。
|
|
20
|
+
* 实例在控件 onMounted 里创建后由返回的 attach 挂载并 resolve whenReady。
|
|
21
|
+
*/
|
|
22
|
+
export declare function createDrawContext(mapId: string, callbacks: DrawContextCallbacks): {
|
|
23
|
+
context: MaplibreDrawContext;
|
|
24
|
+
attach: (draw: TerraDraw) => void;
|
|
25
|
+
};
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { shallowRef } from "vue";
|
|
2
|
+
import { logger } from "../../utils/logger.js";
|
|
3
|
+
const GUIDANCE_KEYS = ["currentlyDrawing", "edited", "selectionPoint", "midPoint", "closingPoint", "snappingPoint", "coordinatePoint"];
|
|
4
|
+
const MODE_BY_GEOMETRY = {
|
|
5
|
+
Point: "point",
|
|
6
|
+
LineString: "linestring",
|
|
7
|
+
Polygon: "polygon"
|
|
8
|
+
};
|
|
9
|
+
export function committedFeatures(draw) {
|
|
10
|
+
return draw.getSnapshot().filter((feature) => !GUIDANCE_KEYS.some((key) => feature.properties[key]));
|
|
11
|
+
}
|
|
12
|
+
function toFeatures(geojson) {
|
|
13
|
+
if (geojson.type === "FeatureCollection") return geojson.features;
|
|
14
|
+
if (geojson.type === "Feature") return [geojson];
|
|
15
|
+
return [{ type: "Feature", properties: {}, geometry: geojson }];
|
|
16
|
+
}
|
|
17
|
+
export function toStoreFeatures(draw, geojson) {
|
|
18
|
+
return toFeatures(geojson).flatMap((feature) => {
|
|
19
|
+
const mode = feature.properties?.mode ?? MODE_BY_GEOMETRY[feature.geometry.type];
|
|
20
|
+
if (!mode) {
|
|
21
|
+
logger.warn(`Draw: unsupported geometry type "${feature.geometry.type}" skipped.`);
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
return [{
|
|
25
|
+
...feature,
|
|
26
|
+
id: feature.id ?? draw.getFeatureId(),
|
|
27
|
+
properties: { ...feature.properties, mode }
|
|
28
|
+
}];
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export function addStoreFeatures(draw, features) {
|
|
32
|
+
if (!features.length) return [];
|
|
33
|
+
return draw.addFeatures(features).flatMap((result) => {
|
|
34
|
+
if (result.valid && result.id !== void 0) return [result.id];
|
|
35
|
+
logger.warn(`Draw: feature "${String(result.id)}" rejected: ${result.reason ?? "invalid"}.`);
|
|
36
|
+
return [];
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export function createDrawContext(mapId, callbacks) {
|
|
40
|
+
const draw = shallowRef();
|
|
41
|
+
let resolveReady;
|
|
42
|
+
const readyPromise = new Promise((resolve) => {
|
|
43
|
+
resolveReady = resolve;
|
|
44
|
+
});
|
|
45
|
+
function attach(instance) {
|
|
46
|
+
draw.value = instance;
|
|
47
|
+
resolveReady(instance);
|
|
48
|
+
}
|
|
49
|
+
async function withDraw(action) {
|
|
50
|
+
const instance = await readyPromise;
|
|
51
|
+
const result = action(instance);
|
|
52
|
+
callbacks.onFeatures(committedFeatures(instance));
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
const context = {
|
|
56
|
+
mapId,
|
|
57
|
+
draw,
|
|
58
|
+
whenReady: () => readyPromise,
|
|
59
|
+
changeMode: async (mode) => {
|
|
60
|
+
const instance = await readyPromise;
|
|
61
|
+
instance.setMode(mode);
|
|
62
|
+
callbacks.onMode(mode);
|
|
63
|
+
},
|
|
64
|
+
add: (geojson) => withDraw((instance) => addStoreFeatures(instance, toStoreFeatures(instance, geojson))),
|
|
65
|
+
deleteAll: () => withDraw((instance) => instance.clear()),
|
|
66
|
+
setFeatureProperty: (featureId, property, value) => withDraw((instance) => {
|
|
67
|
+
instance.updateFeatureProperties(featureId, { [property]: value });
|
|
68
|
+
}),
|
|
69
|
+
getAll: () => draw.value ? { type: "FeatureCollection", features: committedFeatures(draw.value) } : void 0,
|
|
70
|
+
getMode: () => draw.value?.getMode()
|
|
71
|
+
};
|
|
72
|
+
return { context, attach };
|
|
73
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { MaplibreDrawContext } from '../../types';
|
|
2
|
+
export declare function registerDraw(context: MaplibreDrawContext): void;
|
|
3
|
+
/** 按上下文身份注销:过渡期新控件可能先于旧控件卸载完成注册,按 id 删会误删新注册 */
|
|
4
|
+
export declare function unregisterDraw(context: MaplibreDrawContext): void;
|
|
5
|
+
export declare function getDrawContext(mapId: string): MaplibreDrawContext | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { shallowReactive } from "vue";
|
|
2
|
+
import { logger } from "../../utils/logger.js";
|
|
3
|
+
const registry = shallowReactive(/* @__PURE__ */ new Map());
|
|
4
|
+
export function registerDraw(context) {
|
|
5
|
+
if (registry.has(context.mapId)) {
|
|
6
|
+
logger.warn(`map "${context.mapId}" already has a <MaplibreDrawControl>; the latest one takes over.`);
|
|
7
|
+
}
|
|
8
|
+
registry.set(context.mapId, context);
|
|
9
|
+
}
|
|
10
|
+
export function unregisterDraw(context) {
|
|
11
|
+
if (registry.get(context.mapId) === context) registry.delete(context.mapId);
|
|
12
|
+
}
|
|
13
|
+
export function getDrawContext(mapId) {
|
|
14
|
+
return registry.get(mapId);
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IControl } from 'maplibre-gl';
|
|
2
|
+
export interface DrawToolbarOptions {
|
|
3
|
+
/** 按钮对应的模式名,按顺序渲染 */
|
|
4
|
+
modes: string[];
|
|
5
|
+
/** 点击模式按钮 */
|
|
6
|
+
onMode: (mode: string) => void;
|
|
7
|
+
/** 点击删除按钮 */
|
|
8
|
+
onTrash: () => void;
|
|
9
|
+
}
|
|
10
|
+
export interface DrawToolbar extends IControl {
|
|
11
|
+
/** 高亮当前模式按钮 */
|
|
12
|
+
setActive: (mode: string | undefined) => void;
|
|
13
|
+
}
|
|
14
|
+
/** terra-draw 不带 UI,此控件提供模式切换与删除按钮,挂在地图控件槽位 */
|
|
15
|
+
export declare function createDrawToolbar(options: DrawToolbarOptions): DrawToolbar;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const ICONS = {
|
|
2
|
+
select: '<path d="M6 3l12 9-5.5 1.2L15 20l-2.4 1-2.5-6.7L6 18z"/>',
|
|
3
|
+
point: '<circle cx="12" cy="12" r="4" fill="currentColor"/>',
|
|
4
|
+
linestring: '<path d="M4 19l6-10 5 6 5-10"/>',
|
|
5
|
+
polygon: '<path d="M5 18L4 8l8-4 8 5-3 10z"/>',
|
|
6
|
+
rectangle: '<rect x="4" y="6" width="16" height="12"/>',
|
|
7
|
+
circle: '<circle cx="12" cy="12" r="8"/>',
|
|
8
|
+
ellipse: '<ellipse cx="12" cy="12" rx="9" ry="6"/>',
|
|
9
|
+
sector: '<path d="M12 12h8a8 8 0 0 0-8-8z"/>',
|
|
10
|
+
trash: '<path d="M5 7h14M10 7V5h4v2M7 7l1 13h8l1-13"/>'
|
|
11
|
+
};
|
|
12
|
+
const LABELS = {
|
|
13
|
+
select: "Select",
|
|
14
|
+
point: "Point",
|
|
15
|
+
linestring: "Line",
|
|
16
|
+
polygon: "Polygon",
|
|
17
|
+
rectangle: "Rectangle",
|
|
18
|
+
circle: "Circle",
|
|
19
|
+
ellipse: "Ellipse",
|
|
20
|
+
sector: "Sector",
|
|
21
|
+
trash: "Delete"
|
|
22
|
+
};
|
|
23
|
+
function createButton(name, dataset, onClick) {
|
|
24
|
+
const button = document.createElement("button");
|
|
25
|
+
button.type = "button";
|
|
26
|
+
button.className = "movk-draw-toolbar__button";
|
|
27
|
+
button.title = LABELS[name] ?? name;
|
|
28
|
+
button.setAttribute("aria-label", button.title);
|
|
29
|
+
Object.assign(button.dataset, dataset);
|
|
30
|
+
button.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round" stroke-linecap="round">${ICONS[name] ?? ""}</svg>`;
|
|
31
|
+
button.addEventListener("click", onClick);
|
|
32
|
+
return button;
|
|
33
|
+
}
|
|
34
|
+
export function createDrawToolbar(options) {
|
|
35
|
+
const container = document.createElement("div");
|
|
36
|
+
container.className = "maplibregl-ctrl maplibregl-ctrl-group movk-draw-toolbar";
|
|
37
|
+
const modeButtons = options.modes.map((mode) => {
|
|
38
|
+
const button = createButton(mode, { mode }, () => options.onMode(mode));
|
|
39
|
+
container.appendChild(button);
|
|
40
|
+
return button;
|
|
41
|
+
});
|
|
42
|
+
container.appendChild(createButton("trash", { action: "trash" }, options.onTrash));
|
|
43
|
+
return {
|
|
44
|
+
onAdd: () => container,
|
|
45
|
+
onRemove: () => container.remove(),
|
|
46
|
+
setActive(mode) {
|
|
47
|
+
for (const button of modeButtons) {
|
|
48
|
+
button.setAttribute("aria-pressed", String(button.dataset.mode === mode));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DrawKey = Symbol("movk-maplibre:draw");
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { InjectionKey, Ref } from 'vue';
|
|
2
|
+
/** MaplibreLayerGroup 向子图层下发的组上下文 */
|
|
3
|
+
export interface LayerGroupContext {
|
|
4
|
+
/** 组内图层缺省插入锚点(子图层自身 beforeId 优先) */
|
|
5
|
+
beforeId: Ref<string | undefined>;
|
|
6
|
+
/** 组级显隐开关 */
|
|
7
|
+
visible: Ref<boolean>;
|
|
8
|
+
}
|
|
9
|
+
export declare const LayerGroupKey: InjectionKey<LayerGroupContext>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const LayerGroupKey = Symbol("movk-maplibre:layer-group");
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MaplibreContext } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* setup 阶段捕获注入上下文,返回延迟解析器:
|
|
4
|
+
* 显式 mapId 优先查注册表(地图挂载后可得),否则回退当前注入。
|
|
5
|
+
* 供可在 MaplibreMap 子树外使用的交互 composables 共享。
|
|
6
|
+
*/
|
|
7
|
+
export declare function useContextResolver(mapId?: string): () => MaplibreContext | undefined;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { inject } from "vue";
|
|
2
|
+
import { MaplibreContextKey } from "./context.js";
|
|
3
|
+
import { getMapContext } from "./registry.js";
|
|
4
|
+
export function useContextResolver(mapId) {
|
|
5
|
+
const injected = inject(MaplibreContextKey, null);
|
|
6
|
+
return () => mapId ? getMapContext(mapId) : injected ?? void 0;
|
|
7
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Map as MaplibreMap } from 'maplibre-gl';
|
|
2
|
+
/**
|
|
3
|
+
* 样式级效果(sky 等)共享逻辑:
|
|
4
|
+
* 就绪即应用(setStyle 重载后经 onReady 自动重设),来源变化重应用,卸载时清除。
|
|
5
|
+
*/
|
|
6
|
+
export declare function useStyleEffect<T>(source: () => T, apply: (map: MaplibreMap, value: T) => void, clear: (map: MaplibreMap) => void): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { onUnmounted, watch } from "vue";
|
|
2
|
+
import { useMap } from "../../composables/useMap.js";
|
|
3
|
+
export function useStyleEffect(source, apply, clear) {
|
|
4
|
+
const ctx = useMap();
|
|
5
|
+
function safeRun(map, action) {
|
|
6
|
+
try {
|
|
7
|
+
action(map);
|
|
8
|
+
} catch {
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const stopReady = ctx.onReady((map) => apply(map, source()));
|
|
12
|
+
watch(source, (value) => {
|
|
13
|
+
const map = ctx.map.value;
|
|
14
|
+
if (map) safeRun(map, (m) => apply(m, value));
|
|
15
|
+
}, { deep: true });
|
|
16
|
+
onUnmounted(() => {
|
|
17
|
+
stopReady();
|
|
18
|
+
const map = ctx.map.value;
|
|
19
|
+
if (map) safeRun(map, clear);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TerraDrawExtend } from 'terra-draw';
|
|
2
|
+
import type { DrawThemeOptions } from '../utils/draw-theme';
|
|
3
|
+
/** 内置绘制模式名(不含选择模式 'select') */
|
|
4
|
+
export declare const DRAW_MODE_NAMES: readonly ["point", "linestring", "polygon", "rectangle", "circle", "ellipse", "sector"];
|
|
5
|
+
export type DrawModeName = (typeof DRAW_MODE_NAMES)[number];
|
|
6
|
+
/** terra-draw 模式实例(绘制或选择模式) */
|
|
7
|
+
export type DrawMode = TerraDrawExtend.TerraDrawBaseDrawMode<TerraDrawExtend.CustomStyling>;
|
|
8
|
+
export interface MovkDrawModesOptions {
|
|
9
|
+
/** 绘制主题,参见 drawThemeStyles */
|
|
10
|
+
theme?: DrawThemeOptions;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 预设 terra-draw 模式集合:选择模式 + 全部内置绘制模式,统一应用主题。
|
|
14
|
+
* 每次调用返回新实例,模式实例不可在多个 TerraDraw 间共享。
|
|
15
|
+
*/
|
|
16
|
+
export declare function movkDrawModes(options?: MovkDrawModesOptions): DrawMode[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TerraDrawCircleMode,
|
|
3
|
+
TerraDrawEllipseMode,
|
|
4
|
+
TerraDrawLineStringMode,
|
|
5
|
+
TerraDrawPointMode,
|
|
6
|
+
TerraDrawPolygonMode,
|
|
7
|
+
TerraDrawRectangleMode,
|
|
8
|
+
TerraDrawSectorMode,
|
|
9
|
+
TerraDrawSelectMode
|
|
10
|
+
} from "terra-draw";
|
|
11
|
+
import { drawThemeStyles } from "../utils/draw-theme.js";
|
|
12
|
+
export const DRAW_MODE_NAMES = ["point", "linestring", "polygon", "rectangle", "circle", "ellipse", "sector"];
|
|
13
|
+
const EDITABLE_COORDINATES = { draggable: true, deletable: true, midpoints: true };
|
|
14
|
+
export function movkDrawModes(options = {}) {
|
|
15
|
+
const styles = drawThemeStyles(options.theme);
|
|
16
|
+
const flags = Object.fromEntries(DRAW_MODE_NAMES.map((name) => [name, {
|
|
17
|
+
feature: {
|
|
18
|
+
draggable: true,
|
|
19
|
+
...name === "linestring" || name === "polygon" ? { coordinates: EDITABLE_COORDINATES } : {}
|
|
20
|
+
}
|
|
21
|
+
}]));
|
|
22
|
+
return [
|
|
23
|
+
new TerraDrawSelectMode({ flags, styles: styles.select }),
|
|
24
|
+
new TerraDrawPointMode({ styles: styles.point }),
|
|
25
|
+
new TerraDrawLineStringMode({ styles: styles.linestring }),
|
|
26
|
+
new TerraDrawPolygonMode({ styles: styles.polygon }),
|
|
27
|
+
new TerraDrawRectangleMode({ styles: styles.rectangle }),
|
|
28
|
+
new TerraDrawCircleMode({ styles: styles.circle }),
|
|
29
|
+
new TerraDrawEllipseMode({ styles: styles.ellipse }),
|
|
30
|
+
new TerraDrawSectorMode({ styles: styles.sector })
|
|
31
|
+
];
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "maplibre-gl/dist/maplibre-gl.css";
|