@movk/maplibre 1.0.0 → 1.2.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 (202) hide show
  1. package/README.en.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/module.d.mts +12 -3
  4. package/dist/module.d.ts +12 -3
  5. package/dist/module.json +1 -1
  6. package/dist/module.mjs +26 -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/runtime/utils/zzts-tile.d.ts +54 -0
  192. package/dist/runtime/utils/zzts-tile.js +85 -0
  193. package/dist/runtime/utils/zzts.d.ts +14 -0
  194. package/dist/runtime/utils/zzts.js +72 -0
  195. package/dist/unplugin.d.mts +1 -1
  196. package/dist/unplugin.d.ts +1 -1
  197. package/dist/unplugin.mjs +1 -7
  198. package/package.json +29 -21
  199. package/dist/runtime/draw-modes/index.d.ts +0 -16
  200. package/dist/runtime/draw-modes/index.js +0 -32
  201. package/dist/runtime/utils/draw-theme.d.ts +0 -47
  202. /package/dist/runtime/{utils → domains/map}/draw-theme.js +0 -0
@@ -0,0 +1,53 @@
1
+ import {
2
+ TerraDrawCircleMode,
3
+ TerraDrawEllipseMode,
4
+ TerraDrawLineStringMode,
5
+ TerraDrawPointMode,
6
+ TerraDrawPolygonMode,
7
+ TerraDrawRectangleMode,
8
+ TerraDrawSectorMode,
9
+ TerraDrawSelectMode
10
+ } from "terra-draw";
11
+ import { logger } from "../../utils/logger.js";
12
+ import { drawThemeStyles } from "./draw-theme.js";
13
+ export const DRAW_MODE_NAMES = ["select", "point", "linestring", "polygon", "rectangle", "circle", "ellipse", "sector"];
14
+ const EDITABLE_MODES = /* @__PURE__ */ new Set(["linestring", "polygon"]);
15
+ const EDITABLE_COORDINATES = { draggable: true, deletable: true, midpoints: true };
16
+ function selectFlags(names) {
17
+ return Object.fromEntries(names.filter((name) => name !== "select").map((name) => [name, {
18
+ feature: { draggable: true, ...EDITABLE_MODES.has(name) ? { coordinates: EDITABLE_COORDINATES } : {} }
19
+ }]));
20
+ }
21
+ function createMode(name, styles, names) {
22
+ switch (name) {
23
+ case "select":
24
+ return new TerraDrawSelectMode({ flags: selectFlags(names), styles: styles.select });
25
+ case "point":
26
+ return new TerraDrawPointMode({ styles: styles.point });
27
+ case "linestring":
28
+ return new TerraDrawLineStringMode({ styles: styles.linestring });
29
+ case "polygon":
30
+ return new TerraDrawPolygonMode({ styles: styles.polygon });
31
+ case "rectangle":
32
+ return new TerraDrawRectangleMode({ styles: styles.rectangle });
33
+ case "circle":
34
+ return new TerraDrawCircleMode({ styles: styles.circle });
35
+ case "ellipse":
36
+ return new TerraDrawEllipseMode({ styles: styles.ellipse });
37
+ case "sector":
38
+ return new TerraDrawSectorMode({ styles: styles.sector });
39
+ }
40
+ }
41
+ export function isDrawModeName(entry) {
42
+ return typeof entry === "string" && DRAW_MODE_NAMES.includes(entry);
43
+ }
44
+ export function resolveDrawModes(entries, theme) {
45
+ const valid = entries.filter((entry) => {
46
+ if (typeof entry !== "string" || isDrawModeName(entry)) return true;
47
+ logger.warn(`Draw: unknown mode "${entry}" skipped.`);
48
+ return false;
49
+ });
50
+ const styles = drawThemeStyles(theme);
51
+ const names = valid.map((entry) => typeof entry === "string" ? entry : entry.mode);
52
+ return valid.map((entry) => typeof entry === "string" ? createMode(entry, styles, names) : entry);
53
+ }
@@ -1,5 +1,4 @@
1
1
  import type { MaplibreDrawContext } from '../../types';
2
- export declare function registerDraw(context: MaplibreDrawContext): void;
3
- /** 按上下文身份注销:过渡期新控件可能先于旧控件卸载完成注册,按 id 删会误删新注册 */
4
- export declare function unregisterDraw(context: MaplibreDrawContext): void;
2
+ /** 返回按身份校验的注销句柄:过渡期新控件可能先于旧控件卸载完成注册,按 id 删会误删新注册 */
3
+ export declare function registerDraw(context: MaplibreDrawContext): () => void;
5
4
  export declare function getDrawContext(mapId: string): MaplibreDrawContext | undefined;
@@ -1,14 +1,11 @@
1
- import { shallowReactive } from "vue";
1
+ import { createRegistry } from "@movk/core";
2
2
  import { logger } from "../../utils/logger.js";
3
- const registry = shallowReactive(/* @__PURE__ */ new Map());
3
+ const registry = createRegistry({
4
+ reactive: true,
5
+ onDuplicate: (id) => logger.warn(`map "${id}" already has a <MaplibreDrawControl>; the latest one takes over.`)
6
+ });
4
7
  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);
8
+ return registry.register(context.mapId, context);
12
9
  }
13
10
  export function getDrawContext(mapId) {
14
11
  return registry.get(mapId);
@@ -0,0 +1,12 @@
1
+ import type { GeoJSONStoreFeatures, HexColor } from 'terra-draw';
2
+ import type { DrawModeName, DrawThemeOptions } from '../../types';
3
+ type ColorStyle = (feature: GeoJSONStoreFeatures) => HexColor;
4
+ type ModeStyles = Record<string, number | HexColor | ColorStyle>;
5
+ /** 各内置模式的 terra-draw styles,键为模式名 */
6
+ export type DrawThemeStyles = Record<DrawModeName, ModeStyles>;
7
+ /**
8
+ * 生成 terra-draw 各内置模式的主题样式。
9
+ * 要素 `properties.color` 优先于主题色,便于按要素单独着色(配合 setFeatureProperty)。
10
+ */
11
+ export declare function drawThemeStyles(options?: DrawThemeOptions): DrawThemeStyles;
12
+ export {};
@@ -1,14 +1,15 @@
1
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"/>'
2
+ select: '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z"/>',
3
+ point: '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/></g>',
4
+ linestring: '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M4.89 16.21l3.22-6.42M10.2 9.6l3.6 4.8M15.89 14.21l3.22-6.42"/><circle cx="4" cy="18" r="2"/><circle cx="9" cy="8" r="2"/><circle cx="15" cy="16" r="2"/><circle cx="20" cy="6" r="2"/></g>',
5
+ polygon: '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.83 2.38a2 2 0 0 1 2.34 0l8 5.74a2 2 0 0 1 .73 2.25l-3.04 9.26a2 2 0 0 1-1.9 1.37H7.04a2 2 0 0 1-1.9-1.37L2.1 10.37a2 2 0 0 1 .73-2.25z"/>',
6
+ rectangle: '<rect width="20" height="12" x="2" y="6" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" rx="2"/>',
7
+ circle: '<circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>',
8
+ ellipse: '<ellipse cx="12" cy="12" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" rx="10" ry="6"/>',
9
+ sector: '<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z"/><path d="M21.21 15.89A10 10 0 1 1 8 2.83"/></g>',
10
+ trash: '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 11v6m4-6v6m5-11v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>'
11
11
  };
12
+ const FALLBACK_ICON = '<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497zM15 5l4 4"/>';
12
13
  const LABELS = {
13
14
  select: "Select",
14
15
  point: "Point",
@@ -27,7 +28,7 @@ function createButton(name, dataset, onClick) {
27
28
  button.title = LABELS[name] ?? name;
28
29
  button.setAttribute("aria-label", button.title);
29
30
  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.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">${ICONS[name] ?? FALLBACK_ICON}</svg>`;
31
32
  button.addEventListener("click", onClick);
32
33
  return button;
33
34
  }
@@ -1,9 +1,20 @@
1
1
  import type { InjectionKey, Ref } from 'vue';
2
+ import type { LayerSpecification } from '@maplibre/maplibre-gl-style-spec';
3
+ /** 子图层上报给所属组的描述,供图例推导 */
4
+ export interface LayerDescriptor {
5
+ layerId: string;
6
+ type: LayerSpecification['type'];
7
+ paint?: Record<string, unknown>;
8
+ }
2
9
  /** MaplibreLayerGroup 向子图层下发的组上下文 */
3
10
  export interface LayerGroupContext {
4
- /** 组内图层缺省插入锚点(子图层自身 beforeId 优先) */
5
- beforeId: Ref<string | undefined>;
6
- /** 组级显隐开关 */
7
- visible: Ref<boolean>;
11
+ /** 组内图层缺省插入锚点(子图层自身 beforeId 优先,未设置时继承父组) */
12
+ beforeId: Readonly<Ref<string | undefined>>;
13
+ /** 有效显隐:父组有效显隐与自身开关取与 */
14
+ visible: Readonly<Ref<boolean>>;
15
+ /** 有效透明度:父组有效透明度与自身透明度相乘 */
16
+ opacity: Readonly<Ref<number>>;
17
+ /** 上报子图层描述(取值函数,paint 变化随之反映),返回注销函数 */
18
+ registerLayer: (descriptor: () => LayerDescriptor) => () => void;
8
19
  }
9
20
  export declare const LayerGroupKey: InjectionKey<LayerGroupContext>;
@@ -0,0 +1,3 @@
1
+ import type { Registry } from '@movk/core';
2
+ import type { LayerTreeItem, MaplibreContext } from '../../types';
3
+ export declare function getLayerTree(context: MaplibreContext): Registry<LayerTreeItem>;
@@ -0,0 +1,10 @@
1
+ import { createRegistry } from "@movk/core";
2
+ const trees = /* @__PURE__ */ new WeakMap();
3
+ export function getLayerTree(context) {
4
+ let tree = trees.get(context);
5
+ if (!tree) {
6
+ tree = createRegistry({ reactive: true });
7
+ trees.set(context, tree);
8
+ }
9
+ return tree;
10
+ }
@@ -0,0 +1,18 @@
1
+ import type { IControl, StyleSpecification } from 'maplibre-gl';
2
+ export interface MinimapControlOptions {
3
+ /** 鹰眼样式;省略时沿用主图样式并跟随其切换 */
4
+ style?: StyleSpecification | string;
5
+ /** 相对主图的缩放偏移 */
6
+ zoomOffset: number;
7
+ /** 宽度(px) */
8
+ width: number;
9
+ /** 高度(px) */
10
+ height: number;
11
+ /** 视口框颜色 */
12
+ color: string;
13
+ }
14
+ /**
15
+ * 鹰眼控件:容器内新建一个非交互的子地图,随主图移动同步相机并绘制主图视口框;
16
+ * 拖拽鹰眼按像素增量平移主图,单击则把主图中心缓动到点击处。
17
+ */
18
+ export declare function createMinimapControl(options: MinimapControlOptions): IControl;
@@ -0,0 +1,86 @@
1
+ import { omitUndefined } from "@movk/core";
2
+ import { minimapZoom, viewportPolygon } from "../../utils/minimap.js";
3
+ import { createMaplibreGl } from "./create-map.js";
4
+ const SOURCE_ID = "movk-minimap-viewport";
5
+ const FILL_ID = `${SOURCE_ID}-fill`;
6
+ const LINE_ID = `${SOURCE_ID}-line`;
7
+ export function createMinimapControl(options) {
8
+ let parent;
9
+ let mini;
10
+ let container;
11
+ function sync() {
12
+ if (!parent || !mini) return;
13
+ mini.jumpTo({ center: parent.getCenter(), zoom: minimapZoom(parent.getZoom(), options.zoomOffset) });
14
+ const source = mini.getSource(SOURCE_ID);
15
+ source?.setData(viewportPolygon(parent));
16
+ }
17
+ function addViewport() {
18
+ if (!mini || !parent) return;
19
+ mini.addSource(SOURCE_ID, { type: "geojson", data: viewportPolygon(parent) });
20
+ mini.addLayer({ id: FILL_ID, type: "fill", source: SOURCE_ID, paint: { "fill-color": options.color, "fill-opacity": 0.15 } });
21
+ mini.addLayer({ id: LINE_ID, type: "line", source: SOURCE_ID, paint: { "line-color": options.color, "line-width": 2 } });
22
+ sync();
23
+ }
24
+ function followParentStyle() {
25
+ if (parent && mini) mini.setStyle(parent.getStyle(), { diff: false });
26
+ }
27
+ let last;
28
+ let moved = false;
29
+ function onPointerDown(event) {
30
+ last = { x: event.clientX, y: event.clientY };
31
+ moved = false;
32
+ container?.setPointerCapture?.(event.pointerId);
33
+ }
34
+ function onPointerMove(event) {
35
+ if (!last || !parent || !mini) return;
36
+ const dx = event.clientX - last.x;
37
+ const dy = event.clientY - last.y;
38
+ last = { x: event.clientX, y: event.clientY };
39
+ if (!dx && !dy) return;
40
+ moved = true;
41
+ const origin = mini.project(mini.getCenter());
42
+ parent.jumpTo({ center: mini.unproject([origin.x + dx, origin.y + dy]) });
43
+ }
44
+ function onPointerUp(event) {
45
+ if (last && !moved && parent && mini && container) {
46
+ const rect = container.getBoundingClientRect();
47
+ parent.easeTo({ center: mini.unproject([event.clientX - rect.left, event.clientY - rect.top]) });
48
+ }
49
+ last = void 0;
50
+ }
51
+ return {
52
+ onAdd(map) {
53
+ parent = map;
54
+ container = document.createElement("div");
55
+ container.className = "maplibregl-ctrl maplibregl-ctrl-group movk-maplibre-minimap";
56
+ container.style.width = `${options.width}px`;
57
+ container.style.height = `${options.height}px`;
58
+ const style = options.style ?? (map.isStyleLoaded() ? map.getStyle() : void 0);
59
+ mini = createMaplibreGl(omitUndefined({
60
+ container,
61
+ style,
62
+ center: map.getCenter(),
63
+ zoom: minimapZoom(map.getZoom(), options.zoomOffset),
64
+ interactive: false,
65
+ attributionControl: false
66
+ }));
67
+ mini.on("style.load", addViewport);
68
+ map.on("move", sync);
69
+ if (!options.style) map.on("style.load", followParentStyle);
70
+ container.addEventListener("pointerdown", onPointerDown);
71
+ container.addEventListener("pointermove", onPointerMove);
72
+ container.addEventListener("pointerup", onPointerUp);
73
+ container.addEventListener("pointercancel", onPointerUp);
74
+ return container;
75
+ },
76
+ onRemove() {
77
+ parent?.off("move", sync);
78
+ parent?.off("style.load", followParentStyle);
79
+ mini?.remove();
80
+ container?.remove();
81
+ parent = void 0;
82
+ mini = void 0;
83
+ container = void 0;
84
+ }
85
+ };
86
+ }
@@ -1,9 +1,10 @@
1
- const registry = /* @__PURE__ */ new Map();
1
+ import { createRegistry } from "@movk/core";
2
+ const registry = createRegistry({ reactive: true });
2
3
  export function registerMap(context) {
3
- registry.set(context.id, context);
4
+ registry.register(context.id, context);
4
5
  }
5
6
  export function unregisterMap(id) {
6
- registry.delete(id);
7
+ registry.unregister(id);
7
8
  }
8
9
  export function getMapContext(id) {
9
10
  return registry.get(id);
@@ -0,0 +1,7 @@
1
+ import type { Ref } from 'vue';
2
+ import type { StyleLayerPredicate } from '../../types';
3
+ /**
4
+ * 图层组认领底图样式自带的图层:按过滤函数匹配 style.load 快照中的图层,记录原值后按组的
5
+ * 有效显隐与透明度写入。每次样式重载重新匹配,卸载时恢复原值。
6
+ */
7
+ export declare function useStyleLayerAdoption(predicate: () => StyleLayerPredicate | undefined, visible: Readonly<Ref<boolean>>, opacity: Readonly<Ref<number>>): void;
@@ -0,0 +1,54 @@
1
+ import { onUnmounted, watch } from "vue";
2
+ import { useMap } from "../../composables/useMap.js";
3
+ import { opacityPropsFor, scaleOpacity } from "../../utils/layer-opacity.js";
4
+ export function useStyleLayerAdoption(predicate, visible, opacity) {
5
+ const ctx = useMap();
6
+ let adopted = /* @__PURE__ */ new Map();
7
+ function apply(map) {
8
+ for (const [id, original] of adopted) {
9
+ if (!map.getLayer(id)) continue;
10
+ map.setLayoutProperty(id, "visibility", visible.value ? original.visibility : "none");
11
+ for (const [key, value] of Object.entries(original.opacity)) {
12
+ map.setPaintProperty(id, key, scaleOpacity(value, opacity.value));
13
+ }
14
+ }
15
+ }
16
+ function restore(map) {
17
+ for (const [id, original] of adopted) {
18
+ if (!map.getLayer(id)) continue;
19
+ map.setLayoutProperty(id, "visibility", original.visibility);
20
+ for (const [key, value] of Object.entries(original.opacity)) map.setPaintProperty(id, key, value);
21
+ }
22
+ }
23
+ function adopt(map) {
24
+ adopted = /* @__PURE__ */ new Map();
25
+ const match = predicate();
26
+ if (!match) return;
27
+ const snapshot = new Set(ctx.styleLayerIds.value);
28
+ const layers = map.getStyle()?.layers ?? [];
29
+ for (const layer of layers) {
30
+ if (!snapshot.has(layer.id) || !match(layer)) continue;
31
+ const opacityValues = Object.fromEntries(
32
+ opacityPropsFor(layer.type).map((key) => [key, map.getPaintProperty(layer.id, key)])
33
+ );
34
+ adopted.set(layer.id, { visibility: map.getLayoutProperty(layer.id, "visibility"), opacity: opacityValues });
35
+ }
36
+ apply(map);
37
+ }
38
+ const stopReady = ctx.onReady(adopt);
39
+ watch([visible, opacity], () => {
40
+ const map = ctx.map.value;
41
+ if (map && ctx.isStyleReady.value) apply(map);
42
+ });
43
+ watch(predicate, () => {
44
+ const map = ctx.map.value;
45
+ if (!map || !ctx.isStyleReady.value) return;
46
+ restore(map);
47
+ adopt(map);
48
+ });
49
+ onUnmounted(() => {
50
+ stopReady();
51
+ const map = ctx.map.value;
52
+ if (map && ctx.isStyleReady.value) restore(map);
53
+ });
54
+ }
@@ -0,0 +1,3 @@
1
+ import type { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
2
+ /** MapLibre 无内置底图,缺省 style 时实例没有样式,style.load 永不触发;以空白样式兜底(如仅叠加天地图) */
3
+ export declare function blankStyle(): StyleSpecification;
@@ -0,0 +1,5 @@
1
+ import { getMaplibreConfig } from "./config.js";
2
+ export function blankStyle() {
3
+ const { glyphs } = getMaplibreConfig();
4
+ return { version: 8, ...glyphs ? { glyphs } : {}, sources: {}, layers: [] };
5
+ }
@@ -0,0 +1,9 @@
1
+ import type { Map as MaplibreMap } from 'maplibre-gl';
2
+ /**
3
+ * 把对照图绑定到主图:相机、尺寸、投影单向跟随主图,露出区域内的鼠标事件转发给对照图,
4
+ * 对照图设置的光标同步到主图 canvas。返回解绑函数。
5
+ */
6
+ export declare function bindSwipeOverlay(main: MaplibreMap, overlay: MaplibreMap, isRevealed: (point: {
7
+ x: number;
8
+ y: number;
9
+ }) => boolean): () => void;
@@ -0,0 +1,62 @@
1
+ import { MapMouseEvent } from "maplibre-gl";
2
+ const FORWARDED_EVENTS = ["mousedown", "mouseup", "click", "dblclick", "mousemove", "contextmenu"];
3
+ export function bindSwipeOverlay(main, overlay, isRevealed) {
4
+ const syncCamera = () => {
5
+ overlay.jumpTo({
6
+ center: main.getCenter(),
7
+ zoom: main.getZoom(),
8
+ bearing: main.getBearing(),
9
+ pitch: main.getPitch(),
10
+ padding: main.getPadding()
11
+ });
12
+ };
13
+ const syncSize = () => {
14
+ overlay.resize();
15
+ };
16
+ const syncProjection = () => {
17
+ const projection = main.getProjection();
18
+ if (projection) overlay.setProjection(projection);
19
+ };
20
+ let inside = false;
21
+ let mirroredCursor = "";
22
+ function mirrorCursor() {
23
+ const cursor = overlay.getCanvas().style.cursor;
24
+ if (cursor === mirroredCursor) return;
25
+ main.getCanvas().style.cursor = cursor;
26
+ mirroredCursor = cursor;
27
+ }
28
+ function leave(originalEvent) {
29
+ if (!inside) return;
30
+ inside = false;
31
+ overlay.fire(new MapMouseEvent("mouseout", overlay, originalEvent));
32
+ if (mirroredCursor) {
33
+ main.getCanvas().style.cursor = "";
34
+ mirroredCursor = "";
35
+ }
36
+ }
37
+ function forward(event) {
38
+ if (!isRevealed(event.point)) {
39
+ if (event.type === "mousemove") leave(event.originalEvent);
40
+ return;
41
+ }
42
+ inside = true;
43
+ overlay.fire(new MapMouseEvent(event.type, overlay, event.originalEvent));
44
+ if (event.type === "mousemove") mirrorCursor();
45
+ }
46
+ const onMainOut = (event) => leave(event.originalEvent);
47
+ main.on("move", syncCamera);
48
+ main.on("resize", syncSize);
49
+ main.on("projectiontransition", syncProjection);
50
+ overlay.on("style.load", syncProjection);
51
+ for (const type of FORWARDED_EVENTS) main.on(type, forward);
52
+ main.on("mouseout", onMainOut);
53
+ return () => {
54
+ main.off("move", syncCamera);
55
+ main.off("resize", syncSize);
56
+ main.off("projectiontransition", syncProjection);
57
+ overlay.off("style.load", syncProjection);
58
+ for (const type of FORWARDED_EVENTS) main.off(type, forward);
59
+ main.off("mouseout", onMainOut);
60
+ if (mirroredCursor) main.getCanvas().style.cursor = "";
61
+ };
62
+ }
@@ -1 +1 @@
1
- @import "maplibre-gl/dist/maplibre-gl.css";
1
+ @import "maplibre-gl/dist/maplibre-gl.css";.movk-draw-toolbar__button{color:#333}.movk-draw-toolbar__button svg{display:block;margin:auto}.movk-draw-toolbar .movk-draw-toolbar__button[aria-pressed=true]:not(:disabled){background-color:var(--movk-draw-toolbar-active,#3b82f6);color:#fff}
@@ -1,7 +1,40 @@
1
1
  import type { Ref } from 'vue';
2
- import type { TerraDraw, TerraDrawExtend } from 'terra-draw';
2
+ import type { HexColor, TerraDraw, TerraDrawExtend } from 'terra-draw';
3
3
  import type { Feature, FeatureCollection, Geometry } from 'geojson';
4
4
  type FeatureId = TerraDrawExtend.FeatureId;
5
+ /** 内置模式名:选择模式与全部绘制模式 */
6
+ export type DrawModeName = 'select' | 'point' | 'linestring' | 'polygon' | 'rectangle' | 'circle' | 'ellipse' | 'sector';
7
+ /** terra-draw 模式实例(绘制或选择模式) */
8
+ export type DrawMode = TerraDrawExtend.TerraDrawBaseDrawMode<TerraDrawExtend.CustomStyling>;
9
+ /** 模式项:内置模式名(套用主题)或自定义 terra-draw 实例(原样使用) */
10
+ export type DrawModeEntry = DrawModeName | DrawMode;
11
+ export interface DrawThemeOptions {
12
+ /**
13
+ * 非激活态主色,要素 properties.color 优先
14
+ * @defaultValue '#3b82f6'
15
+ */
16
+ color?: HexColor;
17
+ /**
18
+ * 激活态(绘制辅助点/选中)主色
19
+ * @defaultValue '#f59e0b'
20
+ */
21
+ activeColor?: HexColor;
22
+ /**
23
+ * 多边形填充不透明度
24
+ * @defaultValue 0.1
25
+ */
26
+ fillOpacity?: number;
27
+ /**
28
+ * 线宽
29
+ * @defaultValue 2
30
+ */
31
+ lineWidth?: number;
32
+ /**
33
+ * 顶点圆半径
34
+ * @defaultValue 5
35
+ */
36
+ vertexRadius?: number;
37
+ }
5
38
  /**
6
39
  * 由 MaplibreDrawControl 下发的绘制上下文。
7
40
  * 子树内经 useMaplibreDraw() 注入,子树外经 useMaplibreDraw({ mapId }) 查注册表。
@@ -1,3 +1,4 @@
1
1
  export type * from './draw';
2
+ export type * from './layer';
2
3
  export type * from './map';
3
4
  export type * from './tianditu';
@@ -0,0 +1,40 @@
1
+ import type { LayerSpecification, StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
2
+ /** 图例项:面、线、点为单色色块,gradient 为连续色带 */
3
+ export interface LegendItem {
4
+ /** 标签文字 */
5
+ label: string;
6
+ /** 色块形状 */
7
+ type: 'fill' | 'line' | 'circle' | 'gradient';
8
+ /** 单色色块颜色 */
9
+ color?: string;
10
+ /** 渐变色带颜色,按顺序 */
11
+ colors?: string[];
12
+ }
13
+ /** 认领底图样式图层的过滤函数,按图层特征(类型、source-layer 等)匹配 */
14
+ export type StyleLayerPredicate = (layer: LayerSpecification) => boolean;
15
+ /** 图层树中的一项,对应一个带 title 的 MaplibreLayerGroup */
16
+ export interface LayerTreeItem {
17
+ /** 组的唯一标识 */
18
+ id: string;
19
+ /** 组标题 */
20
+ title: string;
21
+ /** 组自身的显隐开关 */
22
+ visible: boolean;
23
+ /** 组自身的透明度 0..1 */
24
+ opacity: number;
25
+ /** 图例项:legend prop 优先,否则由子图层颜色推导 */
26
+ legend: LegendItem[];
27
+ /** 写回组的 v-model:visible */
28
+ setVisible: (visible: boolean) => void;
29
+ /** 写回组的 v-model:opacity */
30
+ setOpacity: (opacity: number) => void;
31
+ }
32
+ /** 底图切换项 */
33
+ export interface BasemapItem {
34
+ /** 显示名称 */
35
+ label: string;
36
+ /** 底图样式(对象或样式 URL);天地图可用 tiandituStyle() 生成 */
37
+ style: StyleSpecification | string;
38
+ /** 缩略图地址;任一项提供时以网格展示 */
39
+ thumbnail?: string;
40
+ }
File without changes
@@ -35,6 +35,12 @@ export interface MaplibreContext {
35
35
  map: ShallowRef<MaplibreMap | undefined>;
36
36
  /** 样式是否已加载完成 */
37
37
  isLoaded: Ref<boolean>;
38
+ /** 当前样式是否已解析(style.load 置真、styledataloading 置假);不受瓦片/源加载影响 */
39
+ isStyleReady: Ref<boolean>;
40
+ /** 当前样式自带的图层 id(每次 style.load 时快照),不含运行时由组件添加的图层 */
41
+ styleLayerIds: Readonly<ShallowRef<readonly string[]>>;
42
+ /** 地图实例创建后 resolve;Marker、Popup、控件、相机等无需等待瓦片加载的操作用它 */
43
+ whenAttached: () => Promise<MaplibreMap>;
38
44
  /** 样式首次加载完成时 resolve */
39
45
  whenLoaded: () => Promise<MaplibreMap>;
40
46
  /**
@@ -0,0 +1,2 @@
1
+ /** 注册 `cog://` 协议(全局单例、幂等),用于直接加载 Cloud Optimized GeoTIFF */
2
+ export declare function registerCogProtocol(): void;
@@ -0,0 +1,9 @@
1
+ import { addProtocol } from "maplibre-gl";
2
+ import { cogProtocol } from "@geomatico/maplibre-cog-protocol";
3
+ import { defineGlobalSingleton } from "@movk/core";
4
+ export function registerCogProtocol() {
5
+ defineGlobalSingleton("movk-maplibre:protocol:cog", () => {
6
+ addProtocol("cog", cogProtocol);
7
+ return true;
8
+ });
9
+ }
@@ -1,3 +1,4 @@
1
+ import { clamp } from "@movk/core";
1
2
  export function arcLine(from, to, options = {}) {
2
3
  const curvature = options.curvature ?? 0.3;
3
4
  const segments = options.segments ?? 64;
@@ -48,7 +49,7 @@ export function ringFade(progress) {
48
49
  export function trailGradient(head, trailLength, color) {
49
50
  const eps = 1e-4;
50
51
  const transparent = "rgba(0, 0, 0, 0)";
51
- const h = Math.min(Math.max(head, eps), 1);
52
+ const h = clamp(head, eps, 1);
52
53
  const tail = Math.max(h - Math.max(trailLength, eps), 0);
53
54
  const expr = ["interpolate", ["linear"], ["line-progress"], tail, transparent, h, color];
54
55
  if (h + eps < 1) expr.push(h + eps, transparent);
@@ -4,3 +4,9 @@ import type { Map as MaplibreMap } from 'maplibre-gl';
4
4
  * 传入 layerId 时绑定到指定图层(用于图层级交互事件)。
5
5
  */
6
6
  export declare function bindMapEvents<E extends string>(map: MaplibreMap, events: readonly E[], handler: (type: E, event: unknown) => void, layerId?: string): () => void;
7
+ /**
8
+ * 目标图层所用 source 的数据变化(setData / setTiles 等)且重新加载完成后,在下一次 render 时回调,返回解绑函数。
9
+ * 仅响应 sourceDataType 为 'content' 的事件,瓦片加载不会触发;同一轮多次变化只回调一次。
10
+ * 不依赖 idle:动效组件逐帧重绘时地图不会进入 idle。
11
+ */
12
+ export declare function onLayerDataChange(map: MaplibreMap, layerId: string, handler: () => void): () => void;
@@ -18,3 +18,28 @@ export function bindMapEvents(map, events, handler, layerId) {
18
18
  }
19
19
  };
20
20
  }
21
+ export function onLayerDataChange(map, layerId, handler) {
22
+ let pendingSource;
23
+ function stop() {
24
+ map.off("render", onRender);
25
+ pendingSource = void 0;
26
+ }
27
+ function onRender() {
28
+ if (!pendingSource) return;
29
+ if (!map.getSource(pendingSource)) return stop();
30
+ if (!map.isSourceLoaded(pendingSource)) return;
31
+ stop();
32
+ handler();
33
+ }
34
+ const onSourceData = (event) => {
35
+ if (pendingSource || event.sourceDataType !== "content") return;
36
+ if (event.sourceId !== map.getLayer(layerId)?.source) return;
37
+ pendingSource = event.sourceId;
38
+ map.on("render", onRender);
39
+ };
40
+ map.on("sourcedata", onSourceData);
41
+ return () => {
42
+ map.off("sourcedata", onSourceData);
43
+ stop();
44
+ };
45
+ }
@@ -11,11 +11,8 @@ export interface FrameStyleImageOptions {
11
11
  frames: () => ImageData[];
12
12
  /** 取地图实例以触发重绘 */
13
13
  getMap: () => MaplibreMap | undefined;
14
- /**
15
- * 固定帧率;durations 缺省时生效
16
- * @defaultValue 12
17
- */
18
- fps?: number;
14
+ /** 固定帧率(响应式取值),durations 缺省时生效;省略时为 12 */
15
+ fps?: () => number;
19
16
  /** 每帧时长 ms(响应式取值),优先于 fps */
20
17
  durations?: () => number[] | undefined;
21
18
  }