@movk/maplibre 1.0.0 → 1.1.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.
Files changed (198) hide show
  1. package/README.en.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/module.d.mts +7 -0
  4. package/dist/module.d.ts +7 -0
  5. package/dist/module.json +1 -1
  6. package/dist/module.mjs +25 -11
  7. package/dist/runtime/components/CustomLayer.d.vue.ts +1 -1
  8. package/dist/runtime/components/CustomLayer.vue +18 -4
  9. package/dist/runtime/components/CustomLayer.vue.d.ts +1 -1
  10. package/dist/runtime/components/Layer.d.vue.ts +4 -4
  11. package/dist/runtime/components/Layer.vue +43 -18
  12. package/dist/runtime/components/Layer.vue.d.ts +4 -4
  13. package/dist/runtime/components/LayerGroup.d.vue.ts +23 -10
  14. package/dist/runtime/components/LayerGroup.vue +44 -4
  15. package/dist/runtime/components/LayerGroup.vue.d.ts +23 -10
  16. package/dist/runtime/components/LottieMarker.d.vue.ts +3 -3
  17. package/dist/runtime/components/LottieMarker.vue +6 -2
  18. package/dist/runtime/components/LottieMarker.vue.d.ts +3 -3
  19. package/dist/runtime/components/Map.d.vue.ts +2 -1
  20. package/dist/runtime/components/Map.vue +2 -6
  21. package/dist/runtime/components/Map.vue.d.ts +2 -1
  22. package/dist/runtime/components/Marker.d.vue.ts +2 -1
  23. package/dist/runtime/components/Marker.vue +33 -9
  24. package/dist/runtime/components/Marker.vue.d.ts +2 -1
  25. package/dist/runtime/components/Popup.d.vue.ts +1 -1
  26. package/dist/runtime/components/Popup.vue +23 -4
  27. package/dist/runtime/components/Popup.vue.d.ts +1 -1
  28. package/dist/runtime/components/Source.d.vue.ts +2 -2
  29. package/dist/runtime/components/Source.vue +3 -15
  30. package/dist/runtime/components/Source.vue.d.ts +2 -2
  31. package/dist/runtime/components/Tooltip.d.vue.ts +2 -2
  32. package/dist/runtime/components/Tooltip.vue +47 -19
  33. package/dist/runtime/components/Tooltip.vue.d.ts +2 -2
  34. package/dist/runtime/components/buffers/BufferCircle.d.vue.ts +1 -1
  35. package/dist/runtime/components/buffers/BufferCircle.vue.d.ts +1 -1
  36. package/dist/runtime/components/buffers/BufferEllipse.d.vue.ts +1 -1
  37. package/dist/runtime/components/buffers/BufferEllipse.vue.d.ts +1 -1
  38. package/dist/runtime/components/buffers/BufferLine.d.vue.ts +1 -1
  39. package/dist/runtime/components/buffers/BufferLine.vue.d.ts +1 -1
  40. package/dist/runtime/components/buffers/BufferPolygon.d.vue.ts +1 -1
  41. package/dist/runtime/components/buffers/BufferPolygon.vue.d.ts +1 -1
  42. package/dist/runtime/components/buffers/BufferSector.d.vue.ts +1 -1
  43. package/dist/runtime/components/buffers/BufferSector.vue.d.ts +1 -1
  44. package/dist/runtime/components/controls/BasemapControl.d.vue.ts +35 -0
  45. package/dist/runtime/components/controls/BasemapControl.vue +60 -0
  46. package/dist/runtime/components/controls/BasemapControl.vue.d.ts +35 -0
  47. package/dist/runtime/components/controls/Control.d.vue.ts +51 -0
  48. package/dist/runtime/components/controls/Control.vue +95 -0
  49. package/dist/runtime/components/controls/Control.vue.d.ts +51 -0
  50. package/dist/runtime/components/controls/GlobeControl.d.vue.ts +18 -0
  51. package/dist/runtime/components/controls/GlobeControl.vue +15 -0
  52. package/dist/runtime/components/controls/GlobeControl.vue.d.ts +18 -0
  53. package/dist/runtime/components/controls/LayerControl.d.vue.ts +44 -0
  54. package/dist/runtime/components/controls/LayerControl.vue +63 -0
  55. package/dist/runtime/components/controls/LayerControl.vue.d.ts +44 -0
  56. package/dist/runtime/components/controls/Legend.d.vue.ts +47 -0
  57. package/dist/runtime/components/controls/Legend.vue +69 -0
  58. package/dist/runtime/components/controls/Legend.vue.d.ts +47 -0
  59. package/dist/runtime/components/controls/Minimap.d.vue.ts +45 -0
  60. package/dist/runtime/components/controls/Minimap.vue +31 -0
  61. package/dist/runtime/components/controls/Minimap.vue.d.ts +45 -0
  62. package/dist/runtime/components/effects/AnimatedImage.d.vue.ts +1 -1
  63. package/dist/runtime/components/effects/AnimatedImage.vue +9 -6
  64. package/dist/runtime/components/effects/AnimatedImage.vue.d.ts +1 -1
  65. package/dist/runtime/components/effects/DiffusionCircle.d.vue.ts +1 -1
  66. package/dist/runtime/components/effects/DiffusionCircle.vue.d.ts +1 -1
  67. package/dist/runtime/components/effects/FlowBuilding.d.vue.ts +1 -1
  68. package/dist/runtime/components/effects/FlowBuilding.vue.d.ts +1 -1
  69. package/dist/runtime/components/effects/GlowCircle.d.vue.ts +1 -1
  70. package/dist/runtime/components/effects/GlowCircle.vue.d.ts +1 -1
  71. package/dist/runtime/components/effects/GradientBuilding.d.vue.ts +1 -1
  72. package/dist/runtime/components/effects/GradientBuilding.vue.d.ts +1 -1
  73. package/dist/runtime/components/effects/Migration.d.vue.ts +1 -1
  74. package/dist/runtime/components/effects/Migration.vue.d.ts +1 -1
  75. package/dist/runtime/components/effects/Radar.d.vue.ts +1 -1
  76. package/dist/runtime/components/effects/Radar.vue.d.ts +1 -1
  77. package/dist/runtime/components/effects/SpriteImage.d.vue.ts +1 -1
  78. package/dist/runtime/components/effects/SpriteImage.vue +40 -24
  79. package/dist/runtime/components/effects/SpriteImage.vue.d.ts +1 -1
  80. package/dist/runtime/components/effects/TextureBuilding.d.vue.ts +1 -1
  81. package/dist/runtime/components/effects/TextureBuilding.vue +1 -1
  82. package/dist/runtime/components/effects/TextureBuilding.vue.d.ts +1 -1
  83. package/dist/runtime/components/effects/Trail.d.vue.ts +1 -1
  84. package/dist/runtime/components/effects/Trail.vue.d.ts +1 -1
  85. package/dist/runtime/components/effects/WaveCircle.d.vue.ts +1 -1
  86. package/dist/runtime/components/effects/WaveCircle.vue.d.ts +1 -1
  87. package/dist/runtime/components/effects/WindowBuilding.d.vue.ts +1 -1
  88. package/dist/runtime/components/effects/WindowBuilding.vue.d.ts +1 -1
  89. package/dist/runtime/components/environment/Projection.d.vue.ts +28 -0
  90. package/dist/runtime/components/environment/Projection.vue +27 -0
  91. package/dist/runtime/components/environment/Projection.vue.d.ts +28 -0
  92. package/dist/runtime/components/environment/Temperature.d.vue.ts +1 -1
  93. package/dist/runtime/components/environment/Temperature.vue.d.ts +1 -1
  94. package/dist/runtime/components/environment/Terrain.d.vue.ts +1 -1
  95. package/dist/runtime/components/environment/Terrain.vue +5 -0
  96. package/dist/runtime/components/environment/Terrain.vue.d.ts +1 -1
  97. package/dist/runtime/components/extensions/DrawControl.vue +23 -19
  98. package/dist/runtime/components/extensions/Swipe.d.vue.ts +48 -0
  99. package/dist/runtime/components/extensions/Swipe.vue +141 -0
  100. package/dist/runtime/components/extensions/Swipe.vue.d.ts +48 -0
  101. package/dist/runtime/components/layers/BuildingLayer.d.vue.ts +1 -1
  102. package/dist/runtime/components/layers/BuildingLayer.vue.d.ts +1 -1
  103. package/dist/runtime/components/layers/ClusterLayer.d.vue.ts +1 -1
  104. package/dist/runtime/components/layers/ClusterLayer.vue.d.ts +1 -1
  105. package/dist/runtime/components/layers/ContourLayer.d.vue.ts +59 -0
  106. package/dist/runtime/components/layers/ContourLayer.vue +84 -0
  107. package/dist/runtime/components/layers/ContourLayer.vue.d.ts +59 -0
  108. package/dist/runtime/components/layers/GraticuleLayer.d.vue.ts +31 -0
  109. package/dist/runtime/components/layers/GraticuleLayer.vue +88 -0
  110. package/dist/runtime/components/layers/GraticuleLayer.vue.d.ts +31 -0
  111. package/dist/runtime/components/layers/ImageLayer.d.vue.ts +1 -1
  112. package/dist/runtime/components/layers/ImageLayer.vue.d.ts +1 -1
  113. package/dist/runtime/components/layers/MaskLayer.d.vue.ts +44 -0
  114. package/dist/runtime/components/layers/MaskLayer.vue +32 -0
  115. package/dist/runtime/components/layers/MaskLayer.vue.d.ts +44 -0
  116. package/dist/runtime/components/layers/RasterLayer.d.vue.ts +5 -3
  117. package/dist/runtime/components/layers/RasterLayer.vue +9 -2
  118. package/dist/runtime/components/layers/RasterLayer.vue.d.ts +5 -3
  119. package/dist/runtime/components/layers/VideoLayer.d.vue.ts +1 -1
  120. package/dist/runtime/components/layers/VideoLayer.vue.d.ts +1 -1
  121. package/dist/runtime/composables/useFeatureState.js +27 -5
  122. package/dist/runtime/composables/useFrameIcon.d.ts +4 -3
  123. package/dist/runtime/composables/useFrameIcon.js +18 -8
  124. package/dist/runtime/composables/useLayerTree.d.ts +11 -0
  125. package/dist/runtime/composables/useLayerTree.js +12 -0
  126. package/dist/runtime/composables/useMapAnimation.d.ts +4 -2
  127. package/dist/runtime/composables/useMapAnimation.js +5 -4
  128. package/dist/runtime/composables/useMapExport.js +2 -5
  129. package/dist/runtime/composables/useMapSync.d.ts +16 -0
  130. package/dist/runtime/composables/useMapSync.js +42 -0
  131. package/dist/runtime/composables/useMaplibreCamera.d.ts +1 -1
  132. package/dist/runtime/composables/useMaplibreCamera.js +1 -1
  133. package/dist/runtime/composables/useMaplibreImage.d.ts +3 -3
  134. package/dist/runtime/composables/useMaplibreImage.js +26 -5
  135. package/dist/runtime/domains/map/config.js +2 -3
  136. package/dist/runtime/domains/map/context.js +15 -0
  137. package/dist/runtime/domains/map/control.d.ts +1 -1
  138. package/dist/runtime/domains/map/control.js +1 -1
  139. package/dist/runtime/domains/map/draw-modes.d.ts +9 -0
  140. package/dist/runtime/domains/map/draw-modes.js +53 -0
  141. package/dist/runtime/domains/map/draw-registry.d.ts +2 -3
  142. package/dist/runtime/domains/map/draw-registry.js +6 -9
  143. package/dist/runtime/domains/map/draw-theme.d.ts +12 -0
  144. package/dist/runtime/domains/map/draw-toolbar.js +11 -10
  145. package/dist/runtime/domains/map/layer-group.d.ts +15 -4
  146. package/dist/runtime/domains/map/layer-tree.d.ts +3 -0
  147. package/dist/runtime/domains/map/layer-tree.js +10 -0
  148. package/dist/runtime/domains/map/minimap.d.ts +18 -0
  149. package/dist/runtime/domains/map/minimap.js +86 -0
  150. package/dist/runtime/domains/map/registry.js +4 -3
  151. package/dist/runtime/domains/map/style-layers.d.ts +7 -0
  152. package/dist/runtime/domains/map/style-layers.js +54 -0
  153. package/dist/runtime/domains/map/style.d.ts +3 -0
  154. package/dist/runtime/domains/map/style.js +5 -0
  155. package/dist/runtime/domains/map/swipe.d.ts +9 -0
  156. package/dist/runtime/domains/map/swipe.js +62 -0
  157. package/dist/runtime/index.css +1 -1
  158. package/dist/runtime/types/draw.d.ts +34 -1
  159. package/dist/runtime/types/index.d.ts +1 -0
  160. package/dist/runtime/types/layer.d.ts +40 -0
  161. package/dist/runtime/types/layer.js +0 -0
  162. package/dist/runtime/types/map.d.ts +6 -0
  163. package/dist/runtime/utils/cog.d.ts +2 -0
  164. package/dist/runtime/utils/cog.js +9 -0
  165. package/dist/runtime/utils/effects.js +2 -1
  166. package/dist/runtime/utils/events.d.ts +6 -0
  167. package/dist/runtime/utils/events.js +25 -0
  168. package/dist/runtime/utils/frame-icon.d.ts +2 -5
  169. package/dist/runtime/utils/frame-icon.js +10 -4
  170. package/dist/runtime/utils/graticule.d.ts +19 -0
  171. package/dist/runtime/utils/graticule.js +62 -0
  172. package/dist/runtime/utils/layer-opacity.d.ts +7 -0
  173. package/dist/runtime/utils/layer-opacity.js +59 -0
  174. package/dist/runtime/utils/layer.js +2 -1
  175. package/dist/runtime/utils/legend.d.ts +9 -0
  176. package/dist/runtime/utils/legend.js +52 -0
  177. package/dist/runtime/utils/marker.d.ts +11 -0
  178. package/dist/runtime/utils/marker.js +28 -0
  179. package/dist/runtime/utils/mask.d.ts +8 -0
  180. package/dist/runtime/utils/mask.js +33 -0
  181. package/dist/runtime/utils/minimap.d.ts +6 -0
  182. package/dist/runtime/utils/minimap.js +15 -0
  183. package/dist/runtime/utils/pmtiles.d.ts +3 -0
  184. package/dist/runtime/utils/pmtiles.js +10 -0
  185. package/dist/runtime/utils/source.d.ts +7 -0
  186. package/dist/runtime/utils/source.js +35 -0
  187. package/dist/runtime/utils/swipe.d.ts +32 -0
  188. package/dist/runtime/utils/swipe.js +18 -0
  189. package/dist/runtime/utils/tianditu.d.ts +10 -1
  190. package/dist/runtime/utils/tianditu.js +11 -0
  191. package/dist/unplugin.d.mts +1 -1
  192. package/dist/unplugin.d.ts +1 -1
  193. package/dist/unplugin.mjs +1 -7
  194. package/package.json +20 -12
  195. package/dist/runtime/draw-modes/index.d.ts +0 -16
  196. package/dist/runtime/draw-modes/index.js +0 -32
  197. package/dist/runtime/utils/draw-theme.d.ts +0 -47
  198. /package/dist/runtime/{utils → domains/map}/draw-theme.js +0 -0
@@ -0,0 +1,44 @@
1
+ import { type MaskInput } from '../../utils/mask';
2
+ /** 区域遮罩:压暗目标区域以外的范围,突出显示行政区等面状区域。 */
3
+ type __VLS_Props = {
4
+ /** 目标区域:Polygon / MultiPolygon / Feature / FeatureCollection;区域自身的孔洞(飞地)不参与遮罩 */
5
+ data: MaskInput;
6
+ /** 图层 id 前缀;省略时自动生成,变更需配合 `:key` 重建 */
7
+ layerId?: string;
8
+ /**
9
+ * 遮罩颜色
10
+ * @defaultValue '#000'
11
+ */
12
+ color?: string;
13
+ /**
14
+ * 遮罩不透明度
15
+ * @defaultValue 0.5
16
+ */
17
+ opacity?: number;
18
+ /**
19
+ * 是否描绘目标区域边界
20
+ * @defaultValue false
21
+ */
22
+ outline?: boolean;
23
+ /**
24
+ * 边界颜色
25
+ * @defaultValue '#fff'
26
+ */
27
+ outlineColor?: string;
28
+ /**
29
+ * 边界宽度(像素)
30
+ * @defaultValue 1
31
+ */
32
+ outlineWidth?: number;
33
+ /** 插入到该图层之前 */
34
+ beforeId?: string;
35
+ };
36
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
37
+ color: string;
38
+ opacity: number;
39
+ outlineColor: string;
40
+ outlineWidth: number;
41
+ outline: boolean;
42
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
43
+ declare const _default: typeof __VLS_export;
44
+ export default _default;
@@ -0,0 +1,32 @@
1
+ <script setup>
2
+ import { computed, useId } from "vue";
3
+ import MaplibreLayer from "../Layer.vue";
4
+ import { maskPolygon } from "../../utils/mask";
5
+ const props = defineProps({
6
+ data: { type: Object, required: true },
7
+ layerId: { type: String, required: false },
8
+ color: { type: String, required: false, default: "#000" },
9
+ opacity: { type: Number, required: false, default: 0.5 },
10
+ outline: { type: Boolean, required: false, default: false },
11
+ outlineColor: { type: String, required: false, default: "#fff" },
12
+ outlineWidth: { type: Number, required: false, default: 1 },
13
+ beforeId: { type: String, required: false }
14
+ });
15
+ const id = props.layerId ?? `movk-mask-${useId()}`;
16
+ const maskSource = computed(() => ({ type: "geojson", data: maskPolygon(props.data) }));
17
+ const outlineSource = computed(() => ({ type: "geojson", data: props.data }));
18
+ const fillPaint = computed(() => ({ "fill-color": props.color, "fill-opacity": props.opacity }));
19
+ const linePaint = computed(() => ({ "line-color": props.outlineColor, "line-width": props.outlineWidth }));
20
+ </script>
21
+
22
+ <template>
23
+ <MaplibreLayer :layer-id="`${id}-fill`" type="fill" :source="maskSource" :paint="fillPaint" :before-id="beforeId" />
24
+ <MaplibreLayer
25
+ v-if="outline"
26
+ :layer-id="`${id}-line`"
27
+ type="line"
28
+ :source="outlineSource"
29
+ :paint="linePaint"
30
+ :before-id="beforeId"
31
+ />
32
+ </template>
@@ -0,0 +1,44 @@
1
+ import { type MaskInput } from '../../utils/mask';
2
+ /** 区域遮罩:压暗目标区域以外的范围,突出显示行政区等面状区域。 */
3
+ type __VLS_Props = {
4
+ /** 目标区域:Polygon / MultiPolygon / Feature / FeatureCollection;区域自身的孔洞(飞地)不参与遮罩 */
5
+ data: MaskInput;
6
+ /** 图层 id 前缀;省略时自动生成,变更需配合 `:key` 重建 */
7
+ layerId?: string;
8
+ /**
9
+ * 遮罩颜色
10
+ * @defaultValue '#000'
11
+ */
12
+ color?: string;
13
+ /**
14
+ * 遮罩不透明度
15
+ * @defaultValue 0.5
16
+ */
17
+ opacity?: number;
18
+ /**
19
+ * 是否描绘目标区域边界
20
+ * @defaultValue false
21
+ */
22
+ outline?: boolean;
23
+ /**
24
+ * 边界颜色
25
+ * @defaultValue '#fff'
26
+ */
27
+ outlineColor?: string;
28
+ /**
29
+ * 边界宽度(像素)
30
+ * @defaultValue 1
31
+ */
32
+ outlineWidth?: number;
33
+ /** 插入到该图层之前 */
34
+ beforeId?: string;
35
+ };
36
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
37
+ color: string;
38
+ opacity: number;
39
+ outlineColor: string;
40
+ outlineWidth: number;
41
+ outline: boolean;
42
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
43
+ declare const _default: typeof __VLS_export;
44
+ export default _default;
@@ -1,8 +1,10 @@
1
1
  type __VLS_Props = {
2
- /** 图层 id;省略时自动生成 */
2
+ /** 图层 id;省略时自动生成,变更需配合 `:key` 重建 */
3
3
  layerId?: string;
4
- /** URL 模板瓦片地址({z}/{x}/{y} 占位) */
5
- tiles: string[];
4
+ /** URL 模板瓦片地址({z}/{x}/{y} 占位);与 `url` 至少提供一个 */
5
+ tiles?: string[];
6
+ /** TileJSON 地址或协议地址(如 `cog://https://.../image.tif`);与 `tiles` 至少提供一个 */
7
+ url?: string;
6
8
  /**
7
9
  * 瓦片尺寸
8
10
  * @defaultValue 256
@@ -3,9 +3,11 @@ import { computed, useId } from "vue";
3
3
  import { omitUndefined } from "@movk/core";
4
4
  import MaplibreSource from "../Source.vue";
5
5
  import MaplibreLayer from "../Layer.vue";
6
+ import { logger } from "../../utils/logger";
6
7
  const props = defineProps({
7
8
  layerId: { type: String, required: false },
8
- tiles: { type: Array, required: true },
9
+ tiles: { type: Array, required: false },
10
+ url: { type: String, required: false },
9
11
  tileSize: { type: Number, required: false, default: 256 },
10
12
  scheme: { type: String, required: false },
11
13
  minzoom: { type: Number, required: false },
@@ -15,9 +17,14 @@ const props = defineProps({
15
17
  beforeId: { type: String, required: false }
16
18
  });
17
19
  const id = props.layerId ?? `movk-raster-${useId()}`;
20
+ const hasSource = computed(() => !!props.url || !!props.tiles?.length);
21
+ if (!hasSource.value) {
22
+ logger.warn('MaplibreRasterLayer: provide either "url" or "tiles".');
23
+ }
18
24
  const source = computed(() => omitUndefined({
19
25
  type: "raster",
20
26
  tiles: props.tiles,
27
+ url: props.url,
21
28
  tileSize: props.tileSize,
22
29
  scheme: props.scheme,
23
30
  minzoom: props.minzoom,
@@ -28,7 +35,7 @@ const paint = computed(() => ({ "raster-opacity": props.opacity }));
28
35
  </script>
29
36
 
30
37
  <template>
31
- <MaplibreSource :source-id="id" :source="source">
38
+ <MaplibreSource v-if="hasSource" :source-id="id" :source="source">
32
39
  <MaplibreLayer :layer-id="id" type="raster" :source="id" :paint="paint" :before-id="beforeId" />
33
40
  </MaplibreSource>
34
41
  </template>
@@ -1,8 +1,10 @@
1
1
  type __VLS_Props = {
2
- /** 图层 id;省略时自动生成 */
2
+ /** 图层 id;省略时自动生成,变更需配合 `:key` 重建 */
3
3
  layerId?: string;
4
- /** URL 模板瓦片地址({z}/{x}/{y} 占位) */
5
- tiles: string[];
4
+ /** URL 模板瓦片地址({z}/{x}/{y} 占位);与 `url` 至少提供一个 */
5
+ tiles?: string[];
6
+ /** TileJSON 地址或协议地址(如 `cog://https://.../image.tif`);与 `tiles` 至少提供一个 */
7
+ url?: string;
6
8
  /**
7
9
  * 瓦片尺寸
8
10
  * @defaultValue 256
@@ -1,6 +1,6 @@
1
1
  import type { VideoSourceSpecification } from '@maplibre/maplibre-gl-style-spec';
2
2
  type __VLS_Props = {
3
- /** 图层 id;省略时自动生成 */
3
+ /** 图层 id;省略时自动生成,变更需配合 `:key` 重建 */
4
4
  layerId?: string;
5
5
  /** 视频地址列表(多格式回退) */
6
6
  urls: string[];
@@ -1,6 +1,6 @@
1
1
  import type { VideoSourceSpecification } from '@maplibre/maplibre-gl-style-spec';
2
2
  type __VLS_Props = {
3
- /** 图层 id;省略时自动生成 */
3
+ /** 图层 id;省略时自动生成,变更需配合 `:key` 重建 */
4
4
  layerId?: string;
5
5
  /** 视频地址列表(多格式回退) */
6
6
  urls: string[];
@@ -1,5 +1,6 @@
1
1
  import { onMounted, onUnmounted, shallowRef } from "vue";
2
2
  import { useContextResolver } from "../domains/map/resolve.js";
3
+ import { onLayerDataChange } from "../utils/events.js";
3
4
  import { logger } from "../utils/logger.js";
4
5
  export function useFeatureState(layerId, options = {}) {
5
6
  const { hover = true, select = true, cursor = true } = options;
@@ -7,6 +8,8 @@ export function useFeatureState(layerId, options = {}) {
7
8
  const hovered = shallowRef();
8
9
  const selected = shallowRef();
9
10
  let boundMap;
11
+ let anchor;
12
+ let stopDataChange;
10
13
  function clearState(map, feature, key) {
11
14
  try {
12
15
  map.removeFeatureState(feature, key);
@@ -17,22 +20,27 @@ export function useFeatureState(layerId, options = {}) {
17
20
  const canvas = map.getCanvas();
18
21
  if (canvas) canvas.style.cursor = value;
19
22
  }
23
+ function setHovered(map, feature) {
24
+ const prev = hovered.value;
25
+ if (prev && prev.id !== feature?.id) clearState(map, prev, "hover");
26
+ if (feature && prev?.id !== feature.id) map.setFeatureState(feature, { hover: true });
27
+ hovered.value = feature;
28
+ }
20
29
  function onMove(event) {
21
30
  const map = boundMap;
22
31
  const feature = event.features?.[0];
23
32
  if (!map || !feature || feature.id === void 0) return;
24
33
  if (cursor) setCursor(map, "pointer");
34
+ anchor = event.lngLat;
25
35
  if (hovered.value?.id === feature.id) return;
26
- if (hovered.value) clearState(map, hovered.value, "hover");
27
- map.setFeatureState(feature, { hover: true });
28
- hovered.value = feature;
36
+ setHovered(map, feature);
29
37
  }
30
38
  function onLeave() {
31
39
  const map = boundMap;
32
40
  if (!map) return;
33
41
  if (cursor) setCursor(map, "");
34
- if (hovered.value) clearState(map, hovered.value, "hover");
35
- hovered.value = void 0;
42
+ anchor = void 0;
43
+ setHovered(map, void 0);
36
44
  }
37
45
  function onClick(event) {
38
46
  const map = boundMap;
@@ -46,6 +54,17 @@ export function useFeatureState(layerId, options = {}) {
46
54
  if (boundMap && selected.value) clearState(boundMap, selected.value, "selected");
47
55
  selected.value = void 0;
48
56
  }
57
+ function revalidate(map) {
58
+ if (hovered.value && anchor) {
59
+ const [feature] = map.queryRenderedFeatures(map.project(anchor), { layers: [layerId] });
60
+ setHovered(map, feature?.id === void 0 ? void 0 : feature);
61
+ }
62
+ const { source, sourceLayer, id } = selected.value ?? {};
63
+ if (source && id !== void 0) {
64
+ const exists = map.querySourceFeatures(source, { sourceLayer, filter: ["==", ["id"], id] }).length > 0;
65
+ if (!exists) clearSelection();
66
+ }
67
+ }
49
68
  onMounted(async () => {
50
69
  const ctx = resolve();
51
70
  if (!ctx) {
@@ -59,6 +78,7 @@ export function useFeatureState(layerId, options = {}) {
59
78
  map.on("mouseleave", layerId, onLeave);
60
79
  }
61
80
  if (select) map.on("click", layerId, onClick);
81
+ stopDataChange = onLayerDataChange(map, layerId, () => revalidate(map));
62
82
  });
63
83
  onUnmounted(() => {
64
84
  const map = boundMap;
@@ -69,6 +89,8 @@ export function useFeatureState(layerId, options = {}) {
69
89
  onLeave();
70
90
  }
71
91
  if (select) map.off("click", layerId, onClick);
92
+ stopDataChange?.();
93
+ stopDataChange = void 0;
72
94
  clearSelection();
73
95
  boundMap = void 0;
74
96
  });
@@ -1,12 +1,13 @@
1
+ import type { MaybeRefOrGetter } from 'vue';
1
2
  export interface UseFrameIconOptions {
2
3
  /** 注册到样式的图片名(symbol 图层 icon-image 引用) */
3
4
  imageName: string;
4
- /** 纹理边长(像素) */
5
- size: number;
5
+ /** 纹理边长(像素);变化时重建 StyleImage */
6
+ size: MaybeRefOrGetter<number>;
6
7
  /** 当前帧序列(响应式取值) */
7
8
  frames: () => ImageData[];
8
9
  /** 固定帧率,durations 缺省时生效 */
9
- fps?: number;
10
+ fps?: MaybeRefOrGetter<number | undefined>;
10
11
  /** 每帧时长 ms(响应式取值),优先于 fps */
11
12
  durations?: () => number[] | undefined;
12
13
  }
@@ -1,16 +1,19 @@
1
- import { onUnmounted } from "vue";
1
+ import { onUnmounted, toValue, watch } from "vue";
2
2
  import { useMap } from "./useMap.js";
3
3
  import { createFrameStyleImage } from "../utils/frame-icon.js";
4
4
  export function useFrameIcon(options) {
5
5
  const ctx = useMap();
6
6
  const { imageName } = options;
7
- const image = createFrameStyleImage({
8
- size: options.size,
9
- frames: options.frames,
10
- fps: options.fps,
11
- durations: options.durations,
12
- getMap: () => ctx.map.value
13
- });
7
+ function create() {
8
+ return createFrameStyleImage({
9
+ size: toValue(options.size),
10
+ frames: options.frames,
11
+ fps: () => toValue(options.fps) ?? 12,
12
+ durations: options.durations,
13
+ getMap: () => ctx.map.value
14
+ });
15
+ }
16
+ let image = create();
14
17
  function ensureImage(map) {
15
18
  if (!map.isStyleLoaded() || map.hasImage(imageName)) return;
16
19
  map.addImage(imageName, image);
@@ -26,6 +29,13 @@ export function useFrameIcon(options) {
26
29
  map.off("styleimagemissing", onMissing);
27
30
  map.on("styleimagemissing", onMissing);
28
31
  });
32
+ watch(() => toValue(options.size), () => {
33
+ image = create();
34
+ const map = ctx.map.value;
35
+ if (!map?.hasImage(imageName)) return;
36
+ map.removeImage(imageName);
37
+ map.addImage(imageName, image);
38
+ });
29
39
  onUnmounted(() => {
30
40
  stopReady();
31
41
  const map = ctx.map.value;
@@ -0,0 +1,11 @@
1
+ import type { ComputedRef } from 'vue';
2
+ import type { LayerTreeItem } from '../types';
3
+ export interface UseLayerTreeOptions {
4
+ /** 目标地图 id;在 MaplibreMap 子树外使用时必填 */
5
+ mapId?: string;
6
+ }
7
+ /**
8
+ * 地图的图层树:按声明顺序列出带 title 的 MaplibreLayerGroup,
9
+ * 读写显隐与透明度即写回各组的 v-model,适合在侧栏等处自绘图层面板。
10
+ */
11
+ export declare function useLayerTree(options?: UseLayerTreeOptions): ComputedRef<LayerTreeItem[]>;
@@ -0,0 +1,12 @@
1
+ import { computed } from "vue";
2
+ import { getLayerTree } from "../domains/map/layer-tree.js";
3
+ import { useContextResolver } from "../domains/map/resolve.js";
4
+ export function useLayerTree(options = {}) {
5
+ const resolve = useContextResolver(options.mapId);
6
+ return computed(() => {
7
+ const context = resolve();
8
+ if (!context) return [];
9
+ const tree = getLayerTree(context);
10
+ return tree.keys().map((id) => tree.get(id));
11
+ });
12
+ }
@@ -16,6 +16,8 @@ export interface UseMapAnimationReturn {
16
16
  }
17
17
  /**
18
18
  * 地图帧动画原语:基于 useRafFn(组件卸载自动停止),
19
- * 仅在地图存在且样式就绪时调用 frame,供动效组件与帧驱动图片复用。
19
+ * 仅在首次 load 之后且样式已解析时调用 frame,供动效组件与帧驱动图片复用。
20
+ * 首次 load 前逐帧改样式会使 style 持续 dirty,推迟 load 及所有 whenLoaded 调用方;
21
+ * 之后不用 isStyleLoaded:它要求瓦片与源全部加载完毕,拖动/缩放或每帧 setData 时会整段跳帧。
20
22
  */
21
- export declare function useMapAnimation(frame: (map: MaplibreMap, elapsedMs: number) => void, options?: UseMapAnimationOptions): UseMapAnimationReturn;
23
+ export declare function useMapAnimation(frame: (map: MaplibreMap, elapsedMs: number, deltaMs: number) => void, options?: UseMapAnimationOptions): UseMapAnimationReturn;
@@ -3,11 +3,12 @@ import { useContextResolver } from "../domains/map/resolve.js";
3
3
  export function useMapAnimation(frame, options = {}) {
4
4
  const resolve = useContextResolver(options.mapId);
5
5
  let start;
6
- const { pause, resume, isActive } = useRafFn(({ timestamp }) => {
7
- const map = resolve()?.map.value;
8
- if (!map || !map.isStyleLoaded()) return;
6
+ const { pause, resume, isActive } = useRafFn(({ timestamp, delta }) => {
7
+ const context = resolve();
8
+ const map = context?.map.value;
9
+ if (!map || !context.isLoaded.value || !context.isStyleReady.value) return;
9
10
  start ??= timestamp;
10
- frame(map, timestamp - start);
11
+ frame(map, timestamp - start, delta);
11
12
  }, { immediate: options.immediate ?? true });
12
13
  return { pause, resume, isActive };
13
14
  }
@@ -1,3 +1,4 @@
1
+ import { triggerDownload } from "@movk/core";
1
2
  import { useContextResolver } from "../domains/map/resolve.js";
2
3
  import { logger } from "../utils/logger.js";
3
4
  export function useMapExport(options = {}) {
@@ -21,11 +22,7 @@ export function useMapExport(options = {}) {
21
22
  }
22
23
  async function download(opts = {}) {
23
24
  try {
24
- const dataUrl = await exportImage(opts);
25
- const link = document.createElement("a");
26
- link.href = dataUrl;
27
- link.download = opts.fileName ?? "map.png";
28
- link.click();
25
+ triggerDownload(await exportImage(opts), opts.fileName ?? "map.png");
29
26
  } catch (error) {
30
27
  logger.warn("Map export failed:", error);
31
28
  throw error;
@@ -0,0 +1,16 @@
1
+ import type { MaybeRefOrGetter } from 'vue';
2
+ import type { MaplibreContext } from '../types';
3
+ export interface UseMapSyncOptions {
4
+ /**
5
+ * 是否启用联动;置 false 解绑,恢复时以首图相机重新对齐
6
+ * @defaultValue true
7
+ */
8
+ enabled?: MaybeRefOrGetter<boolean>;
9
+ }
10
+ /** 地图引用:map id(经注册表解析,需 MaplibreMap 设置 map-id)或地图上下文 */
11
+ export type MapSyncTarget = string | MaplibreContext;
12
+ /**
13
+ * 多地图相机联动:任一地图移动时把 center/zoom/bearing/pitch 同步到其余地图。
14
+ * 全部地图实例就绪后生效,绑定时以首图相机对齐其余地图;随调用方作用域销毁自动解绑。
15
+ */
16
+ export declare function useMapSync(maps: MaybeRefOrGetter<MapSyncTarget[]>, options?: UseMapSyncOptions): void;
@@ -0,0 +1,42 @@
1
+ import { toValue, watch } from "vue";
2
+ import { getMapContext } from "../domains/map/registry.js";
3
+ function resolveInstance(target) {
4
+ const context = typeof target === "string" ? getMapContext(target) : target;
5
+ return context?.map.value;
6
+ }
7
+ function copyCamera(from, to) {
8
+ to.jumpTo({
9
+ center: from.getCenter(),
10
+ zoom: from.getZoom(),
11
+ bearing: from.getBearing(),
12
+ pitch: from.getPitch()
13
+ });
14
+ }
15
+ export function useMapSync(maps, options = {}) {
16
+ watch(
17
+ () => {
18
+ if (toValue(options.enabled) === false) return [];
19
+ const instances = toValue(maps).map(resolveInstance);
20
+ return instances.every(Boolean) ? instances : [];
21
+ },
22
+ (instances, _, onCleanup) => {
23
+ if (instances.length < 2) return;
24
+ let syncing = false;
25
+ const listeners = instances.map((source) => {
26
+ const listener = () => {
27
+ if (syncing) return;
28
+ syncing = true;
29
+ for (const target of instances) {
30
+ if (target !== source) copyCamera(source, target);
31
+ }
32
+ syncing = false;
33
+ };
34
+ source.on("move", listener);
35
+ return listener;
36
+ });
37
+ listeners[0]();
38
+ onCleanup(() => instances.forEach((map, i) => map.off("move", listeners[i])));
39
+ },
40
+ { immediate: true }
41
+ );
42
+ }
@@ -11,5 +11,5 @@ export interface UseMaplibreCameraReturn {
11
11
  /** 缩放到目标范围;target 支持包围盒或任意 GeoJSON(自动求包围盒) */
12
12
  fitBounds: (target: LngLatBoundsLike | GeoJSON, options?: FitBoundsOptions) => Promise<void>;
13
13
  }
14
- /** 相机操作助手;所有方法等待地图加载完成后执行。 */
14
+ /** 相机操作助手;所有方法等待地图实例创建后执行。 */
15
15
  export declare function useMaplibreCamera(options?: UseMaplibreCameraOptions): UseMaplibreCameraReturn;
@@ -12,7 +12,7 @@ export function useMaplibreCamera(options = {}) {
12
12
  logger.warn("useMaplibreCamera: no map context found; pass options.mapId or call inside <MaplibreMap>.");
13
13
  return;
14
14
  }
15
- action(await ctx.whenLoaded());
15
+ action(await ctx.whenAttached());
16
16
  }
17
17
  return {
18
18
  flyTo: (options2) => withMap((map) => map.flyTo(options2)),
@@ -1,4 +1,4 @@
1
- import type { Ref } from 'vue';
1
+ import type { MaybeRefOrGetter, Ref } from 'vue';
2
2
  export interface UseMaplibreImageOptions {
3
3
  /** 目标地图 id;在 MaplibreMap 子树外使用时必填 */
4
4
  mapId?: string;
@@ -12,8 +12,8 @@ export interface UseMaplibreImageOptions {
12
12
  }
13
13
  /**
14
14
  * 注册 symbol 图层可用的命名图片。
15
- * setStyle 清空样式图片后经 onReady 自动补回;卸载时移除。
15
+ * setStyle 清空样式图片后经 onReady 自动补回;url 变化时加载新图并替换同名图片;卸载时移除。
16
16
  */
17
- export declare function useMaplibreImage(name: string, url: string, options?: UseMaplibreImageOptions): {
17
+ export declare function useMaplibreImage(name: string, url: MaybeRefOrGetter<string>, options?: UseMaplibreImageOptions): {
18
18
  loaded: Ref<boolean>;
19
19
  };
@@ -1,4 +1,4 @@
1
- import { onMounted, onUnmounted, ref } from "vue";
1
+ import { onMounted, onUnmounted, ref, toValue, watch } from "vue";
2
2
  import { useContextResolver } from "../domains/map/resolve.js";
3
3
  import { logger } from "../utils/logger.js";
4
4
  export function useMaplibreImage(name, url, options = {}) {
@@ -7,6 +7,25 @@ export function useMaplibreImage(name, url, options = {}) {
7
7
  const loaded = ref(false);
8
8
  let ctx;
9
9
  let stopReady;
10
+ let loadToken = 0;
11
+ function load(map, replace) {
12
+ const token = ++loadToken;
13
+ const src = toValue(url);
14
+ map.loadImage(src).then(({ data }) => {
15
+ if (token !== loadToken) return;
16
+ if (map.hasImage(name)) {
17
+ if (!replace) {
18
+ loaded.value = true;
19
+ return;
20
+ }
21
+ map.removeImage(name);
22
+ }
23
+ map.addImage(name, data, imageOptions);
24
+ loaded.value = true;
25
+ }).catch((error) => {
26
+ if (token === loadToken) logger.warn(`Failed to load image "${name}" from "${src}":`, error);
27
+ });
28
+ }
10
29
  onMounted(() => {
11
30
  ctx = resolve();
12
31
  if (!ctx) {
@@ -18,13 +37,15 @@ export function useMaplibreImage(name, url, options = {}) {
18
37
  loaded.value = true;
19
38
  return;
20
39
  }
21
- map.loadImage(url).then(({ data }) => {
22
- if (!map.hasImage(name)) map.addImage(name, data, imageOptions);
23
- loaded.value = true;
24
- }).catch((error) => logger.warn(`Failed to load image "${name}":`, error));
40
+ load(map, false);
25
41
  });
26
42
  });
43
+ watch(() => toValue(url), () => {
44
+ const map = ctx?.map.value;
45
+ if (map?.isStyleLoaded()) load(map, true);
46
+ });
27
47
  onUnmounted(() => {
48
+ loadToken++;
28
49
  stopReady?.();
29
50
  const map = ctx?.map.value;
30
51
  if (map?.hasImage(name)) map.removeImage(name);
@@ -1,6 +1,5 @@
1
- const STORE_KEY = Symbol.for("movk-maplibre:config");
2
- const globalScope = globalThis;
3
- const store = globalScope[STORE_KEY] ??= { config: {} };
1
+ import { defineGlobalSingleton } from "@movk/core";
2
+ const store = defineGlobalSingleton("movk-maplibre:config", () => ({ config: {} }));
4
3
  export function setMaplibreConfig(value) {
5
4
  store.config = { ...store.config, ...value };
6
5
  }
@@ -3,18 +3,30 @@ export const MaplibreContextKey = Symbol("movk-maplibre:context");
3
3
  export function createMaplibreContext(id) {
4
4
  const map = shallowRef();
5
5
  const isLoaded = ref(false);
6
+ const isStyleReady = ref(false);
7
+ const styleLayerIds = shallowRef([]);
6
8
  const readyCallbacks = /* @__PURE__ */ new Set();
9
+ let resolveAttached;
10
+ const attachedPromise = new Promise((resolve) => {
11
+ resolveAttached = resolve;
12
+ });
7
13
  let resolveLoaded;
8
14
  const loadedPromise = new Promise((resolve) => {
9
15
  resolveLoaded = resolve;
10
16
  });
11
17
  function attach(instance) {
12
18
  map.value = instance;
19
+ resolveAttached(instance);
13
20
  instance.on("load", () => {
14
21
  isLoaded.value = true;
15
22
  resolveLoaded(instance);
16
23
  });
24
+ instance.on("styledataloading", () => {
25
+ isStyleReady.value = false;
26
+ });
17
27
  instance.on("style.load", () => {
28
+ isStyleReady.value = true;
29
+ styleLayerIds.value = instance.getLayersOrder();
18
30
  for (const callback of readyCallbacks) callback(instance);
19
31
  });
20
32
  }
@@ -22,6 +34,9 @@ export function createMaplibreContext(id) {
22
34
  id,
23
35
  map,
24
36
  isLoaded,
37
+ isStyleReady,
38
+ styleLayerIds,
39
+ whenAttached: () => attachedPromise,
25
40
  whenLoaded: () => loadedPromise,
26
41
  onReady(callback) {
27
42
  readyCallbacks.add(callback);
@@ -1,4 +1,4 @@
1
1
  import type { MaybeRefOrGetter } from 'vue';
2
2
  import type { ControlPosition, IControl } from 'maplibre-gl';
3
- /** 控件组件共享逻辑:地图就绪后 addControl;position/options 变化时移除并按新配置重建;卸载时 removeControl。 */
3
+ /** 控件组件共享逻辑:地图实例创建后 addControl;position/options 变化时移除并按新配置重建;卸载时 removeControl。 */
4
4
  export declare function useControl(create: () => IControl, position?: MaybeRefOrGetter<ControlPosition | undefined>, watchSource?: () => unknown): void;
@@ -11,7 +11,7 @@ export function useControl(create, position, watchSource) {
11
11
  map.addControl(control, toValue(position));
12
12
  }
13
13
  onMounted(async () => {
14
- await ctx.whenLoaded();
14
+ await ctx.whenAttached();
15
15
  rebuild();
16
16
  });
17
17
  watch(
@@ -0,0 +1,9 @@
1
+ import type { DrawMode, DrawModeEntry, DrawModeName, DrawThemeOptions } from '../../types';
2
+ /** 全部内置模式名,即控件缺省的模式集合 */
3
+ export declare const DRAW_MODE_NAMES: readonly DrawModeName[];
4
+ export declare function isDrawModeName(entry: DrawModeEntry): entry is DrawModeName;
5
+ /**
6
+ * 解析模式项为 terra-draw 实例:模式名按主题构造内置模式,实例原样透传。
7
+ * 每次调用返回新实例,模式实例不可在多个 TerraDraw 间共享。
8
+ */
9
+ export declare function resolveDrawModes(entries: readonly DrawModeEntry[], theme?: DrawThemeOptions): DrawMode[];