@caoguo/maplibre 0.0.2 → 0.0.5

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/dist/index.d.ts CHANGED
@@ -181,16 +181,89 @@ declare class ThemeSwitcher {
181
181
  remove(): void;
182
182
  }
183
183
 
184
+ /**
185
+ * 图例控件(通用)。
186
+ *
187
+ * 行业专题图(水深色阶 / 光缆利用率 / 闸站状态 / 故障告警等)渲染后,
188
+ * 需要用户可读的图例说明。本控件接收数据驱动的图例项(label + color),
189
+ * 以「色块 + 文案」形式渲染;支持运行时 setItems 随图层切换更新。
190
+ *
191
+ * 设计为「纯函数 renderLegendHtml + 薄 DOM 绑定」:renderLegendHtml 不依赖浏览器,可独立单测。
192
+ */
193
+ interface LegendItem {
194
+ /** 文案,如「水深 > 3m」「利用率高」 */
195
+ label: string;
196
+ /** 色值(CSS color,可与渲染层 paint 配色保持一致) */
197
+ color: string;
198
+ /** 标记形状:color 色块(默认)/ line 线段 */
199
+ shape?: 'color' | 'line';
200
+ }
201
+ interface LegendOptions {
202
+ /** 图例标题(可选) */
203
+ title?: string;
204
+ /** 图例项 */
205
+ items: LegendItem[];
206
+ /** 挂载容器(可选;不传则自动创建) */
207
+ container?: HTMLElement;
208
+ }
209
+ /** 纯函数:根据图例项生成 HTML 字符串(可单测) */
210
+ declare function renderLegendHtml(items: LegendItem[], title?: string): string;
211
+ /** 图例控件 */
212
+ declare class LegendControl {
213
+ private el;
214
+ private bodyEl;
215
+ private opts;
216
+ constructor(options: LegendOptions);
217
+ private render;
218
+ /** 运行时更新图例项(随图层切换重新渲染) */
219
+ setItems(items: LegendItem[], title?: string): void;
220
+ /** 挂载到容器 */
221
+ addTo(container: HTMLElement): this;
222
+ remove(): void;
223
+ }
224
+
225
+ /**
226
+ * 地图导出控件(通用)。
227
+ *
228
+ * 行业专题图渲染后,常需导出当前视图为成果图(PNG)。
229
+ * 基于 maplibre-gl 画布 `toDataURL('image/png')` 生成截图并触发浏览器下载。
230
+ *
231
+ * 设计为「纯函数 triggerDownload + 薄 DOM 绑定」:triggerDownload 不依赖地图,可独立单测。
232
+ */
233
+ interface ExportOptions {
234
+ /** 下载文件名(不含扩展名) */
235
+ filename?: string;
236
+ /** 挂载容器(可选;不传则自动创建) */
237
+ container?: HTMLElement;
238
+ /** 按钮文案 */
239
+ buttonText?: string;
240
+ }
241
+ /** 纯函数:触发浏览器下载(data URL) */
242
+ declare function triggerDownload(dataUrl: string, filename: string): void;
243
+ /** 导出控件 */
244
+ declare class ExportControl {
245
+ private el;
246
+ private map;
247
+ private filename;
248
+ private onClick;
249
+ constructor(map: ExportControl['map'], options?: ExportOptions);
250
+ /** 导出当前地图视图为 PNG 并下载 */
251
+ export(): void;
252
+ /** 挂载到容器 */
253
+ addTo(container: HTMLElement): this;
254
+ remove(): void;
255
+ }
256
+
184
257
  /**
185
258
  * 辉光线几何构建(T6 / F-1.3 纯逻辑部分)。
186
259
  *
187
- * 把 GeoJSON LineString 集合转换为「多遍辉光描边」所需的几何描述。
188
- * 渲染层(CustomLineLayer)再据此在 WebGL 中绘制:每遍一个宽度档 + 透明度档,
189
- * 叠加形成管线/路网/水系的辉光效果。
260
+ * 把 GeoJSON LineString 集合转换为「多遍描边」所需的三角形带几何。
261
+ * 渲染层(CustomLineLayer)据此在 WebGL 中以屏幕像素宽度的三角面叠加绘制,
262
+ * 每遍一个宽度档 + 透明度档,加法混合形成管线/路网/水系的辉光效果。
190
263
  *
191
264
  * 设计:本模块**不依赖 WebGL / maplibre**,纯函数可在 Node 单测。
192
265
  * 坐标投影使用简化 Web Mercator(经度→x、纬度→y 的归一化世界坐标),
193
- * 真实渲染时由 CustomLayer 的 matrix 变换到屏幕。
266
+ * 真实渲染时由 CustomLayer 的 matrix 变换到屏幕;线宽在屏幕空间计算。
194
267
  */
195
268
  interface GlowLine {
196
269
  /** 线坐标 [lng, lat][] */
@@ -199,54 +272,61 @@ interface GlowLine {
199
272
  group?: string;
200
273
  }
201
274
  interface GlowPass {
202
- /** 相对基础宽度的倍数(核心线=1,外晕逐遍增大) */
203
- widthScale: number;
275
+ /** 该遍屏幕像素宽度 */
276
+ width: number;
204
277
  /** 该遍不透明度(核心线高、外晕低) */
205
278
  opacity: number;
206
279
  }
207
280
  interface GlowGeometry {
208
- /** 所有线(含分组标记)的归一化坐标序列 */
209
- lines: {
210
- points: [number, number][];
211
- group?: string;
281
+ /**
282
+ * 扁平化顶点缓冲。每个顶点 5 个 float:
283
+ * [worldX, worldY, dirX, dirY, side]
284
+ * - worldX/worldY:该端点的归一化世界坐标
285
+ * - dirX/dirY:所在线段的世界空间方向(用于屏幕空间法线)
286
+ * - side:±1,左/右扩展符号
287
+ */
288
+ vertices: Float32Array;
289
+ /** 每遍在 vertices 中的顶点区间 [start, count](按顶点数,非 float 数) */
290
+ passRanges: {
291
+ start: number;
292
+ count: number;
212
293
  }[];
213
- /** 辉光多遍参数(从外晕到核心,或反之,由渲染层决定) */
294
+ /** 每遍参数(从最外晕到核心,由宽到窄) */
214
295
  passes: GlowPass[];
215
- /** 总顶点数(用于缓冲分配) */
216
- vertexCount: number;
296
+ /** 顶点属性跨距(float 数) */
297
+ stride: number;
217
298
  }
218
299
  /**
219
300
  * 生成辉光多遍档位。
220
301
  * @param passes 遍数(默认 4:3 层外晕 + 1 核心)
221
- * @param coreOpacity 核心线不透明度
302
+ * @param baseWidth 核心线像素宽度(默认 3)
222
303
  */
223
- declare function glowPasses(passes?: number, coreOpacity?: number): GlowPass[];
304
+ declare function glowPasses(passes?: number, baseWidth?: number): GlowPass[];
224
305
  /**
225
- * 简化 Web Mercator 归一化(经度→x∈[-1,1],纬度→y∈[-1,1])。
306
+ * 简化 Web Mercator 归一化(经度→x∈[-1,1],纬度→y 经墨卡托压缩)。
226
307
  * 仅用于几何构建与单测,真实投影在渲染层用 map 的 matrix。
227
308
  */
228
309
  declare function projectSimple(lng: number, lat: number): [number, number];
229
310
  /**
230
- * 构建辉光几何:投影每条线并统计顶点。
231
- * 顶点数 = 各线(点数-1)*2(线段两端),用于 Line 绘制。
311
+ * 构建辉光几何:对每条线、每遍、每段生成三角面(2 三角形 = 6 顶点)。
232
312
  */
233
313
  declare function buildGlowGeometry(lines: GlowLine[], opts?: {
234
314
  passes?: number;
235
- coreOpacity?: number;
315
+ baseWidth?: number;
236
316
  }): GlowGeometry;
237
317
 
238
318
  /**
239
319
  * 辉光管线 Custom Layer(T6 / F-1.3 WebGL 渲染层)。
240
320
  *
241
321
  * 实现 MapLibre v4 `CustomLayerInterface`:在地图之上叠加绘制 GeoJSON 线,
242
- * 用多遍(glowPasses)描边形成管线/路网/水系的辉光效果。
322
+ * 用多遍(glowPasses)三角面描边形成管线/路网/水系的辉光效果。
243
323
  *
244
- * 设计:几何构建(投影/档位)在 `./glowGeometry` 纯函数中完成(可单测);
324
+ * 设计:几何构建(投影/三角带)在 `./glowGeometry` 纯函数中完成(可单测);
245
325
  * 本文件仅负责 WebGL 状态机与绘制,仅在浏览器执行。
326
+ * 线宽在屏幕空间按像素计算(标准 Mapbox line shader 思路),因此可随缩放保持视觉宽度。
246
327
  * 通过 `Map.addGlowLayer` 注入,调用方无需感知 WebGL 细节。
247
328
  *
248
- * 依赖 MapLibre 注入的 `matrix`(map 的 projectionMatrix * modelViewMatrix),
249
- * 与官方 CustomLayer 示例一致。
329
+ * 依赖 MapLibre 注入的 `matrix`(map 的 projectionMatrix * modelViewMatrix)。
250
330
  */
251
331
 
252
332
  /** MapLibre v4 CustomLayerInterface 最小子集(避免强类型耦合) */
@@ -278,7 +358,6 @@ declare class CustomLineLayer implements CustomLayerInterface {
278
358
  private lines;
279
359
  private colors;
280
360
  private baseWidth;
281
- private passes;
282
361
  private program?;
283
362
  private buffer?;
284
363
  private geometry;
@@ -350,8 +429,93 @@ declare class LodController<T = unknown> {
350
429
  remove(): void;
351
430
  }
352
431
 
432
+ /**
433
+ * 原生 MapLibre 地图 source 操作的幂等工具。
434
+ *
435
+ * 各业务 System(grid/water/pipeline/telecom/compute/transport)的 render()
436
+ * 通过 `this.map.instance` 直接调用原生 MapLibre,而非经 CaoguoMap 包装类的
437
+ * 幂等 addSource。为避免在每个 System 内重复书写 `if (!mlMap.getSource(id))`
438
+ * 样板,并根治「层级切换重渲染崩溃」(Source already exists),统一在此提供
439
+ * 幂等 upsert 与安全的 removeSource。
440
+ *
441
+ * 仅依赖原生 MapLibre 的 source 子集接口,便于各 System 直接传入 instance。
442
+ */
443
+ /**
444
+ * 原生 MapLibre source 操作的子集接口。
445
+ *
446
+ * 仅 `getSource` 为必填——它是所有 helper 判断「source 是否存在」的统一探针。
447
+ * 其余方法全部可选,因为各业务 System 对 `this.map.instance` 的局部类型断言
448
+ * 只声明了实际用到的若干方法(如 topology 只取 getSource/removeSource,
449
+ * traffic 只取 addSource/addLayer),强制统一必填字段会与这些子集冲突。
450
+ * helper 内部对每个要调用的方法做存在性检查,缺失时安全跳过或回退,
451
+ * 保证类型与运行时都安全(真实 MapLibre 实例始终具备全部方法)。
452
+ */
453
+ interface MlMapSourceApi {
454
+ getSource: (id: string) => unknown;
455
+ addSource?: (id: string, source: unknown) => void;
456
+ addLayer?: (layer: unknown) => void;
457
+ setData?: (id: string, data: unknown) => void;
458
+ removeSource?: (id: string) => void;
459
+ }
460
+ /**
461
+ * 幂等地确保一个 GeoJSON source 存在并持有给定数据。
462
+ *
463
+ * - 若 source 已存在且具备 setData:setData 更新(避免重复 addSource 抛错)。
464
+ * - 若 source 已存在但无 setData:回退为 addSource(MapLibre 对重复 id 会忽略/覆盖,
465
+ * 不抛错,仍可达成渲染目标)。
466
+ * - 若 source 不存在且具备 addSource:addSource 创建。
467
+ *
468
+ * 注意:若传入对象既无 setData 又无 addSource,则无法创建/更新 source。
469
+ * 各 System 传入的 `this.map.instance` 为真实 MapLibre 实例,始终具备这些方法。
470
+ *
471
+ * @param mlMap 原生 MapLibre 实例(或任意满足 MlMapSourceApi 的对象)
472
+ * @param id source 唯一标识
473
+ * @param data GeoJSON 数据(或 addSource 所需的 source spec)
474
+ */
475
+ declare function upsertSource(mlMap: MlMapSourceApi, id: string, data: unknown): void;
476
+ /**
477
+ * 安全地移除 source:仅当存在且具备 removeSource 时才移除,避免不存在时抛错。
478
+ *
479
+ * @param mlMap 原生 MapLibre 实例
480
+ * @param id source 唯一标识
481
+ */
482
+ declare function removeSourceSafe(mlMap: MlMapSourceApi, id: string): void;
483
+ /**
484
+ * 安全地批量移除 source。
485
+ *
486
+ * @param mlMap 原生 MapLibre 实例
487
+ * @param ids source 标识数组
488
+ */
489
+ declare function removeSourcesSafe(mlMap: MlMapSourceApi, ids: string[]): void;
490
+
353
491
  type MapInstance = Map$1;
492
+ /**
493
+ * WebGL 不可用时抛出(如无 GPU 的沙箱/无头环境、老旧浏览器)。
494
+ * 调用方应捕获并向用户展示降级提示,而非让页面崩溃。
495
+ */
496
+ declare class WebGLUnavailableError extends Error {
497
+ constructor(message?: string);
498
+ }
499
+ /**
500
+ * 探测当前环境是否可创建真正可用的 WebGL 上下文。
501
+ * 某些沙箱/无头浏览器会返回 canvas,且 getContext 也返回一个「伪对象」,
502
+ * 但上下文实际不可用(渲染时崩溃)。因此除了非 null 判断,还进一步验证
503
+ * 上下文确实能工作:能读出 VENDOR、能取到必要扩展,并捕获
504
+ * webglcontextcreationerror 事件。
505
+ */
506
+ declare function isWebGLAvailable(): boolean;
354
507
 
508
+ /**
509
+ * 全局配置(由应用入口注入一次,所有 Map 实例共享)。
510
+ * 用于把敏感 token(如天地图 key)从库内部解耦到应用侧,
511
+ * 避免硬编码、避免库 dist 中无法替换 import.meta.env 的问题。
512
+ */
513
+ interface CaoguoMapGlobalConfig {
514
+ /** 天地图 token;未显式给 Map 传 tianditu 时自动生效 */
515
+ tiandituToken?: string;
516
+ }
517
+ declare function setGlobalConfig(cfg: CaoguoMapGlobalConfig): void;
518
+ declare function getGlobalConfig(): CaoguoMapGlobalConfig;
355
519
  interface MapOptions {
356
520
  container: string | HTMLElement;
357
521
  center?: [number, number];
@@ -365,6 +529,19 @@ interface MapOptions {
365
529
  * 设定后可通过 `transformToMap` 在入图前自动纠偏。
366
530
  */
367
531
  dataCRS?: CRS;
532
+ /**
533
+ * 天地图(Tianditu)底图选项。传入后,**默认底图从 OSM 切换为天地图**
534
+ * (国内权威底图,CGCS2000 / Web Mercator,适配国内网络与坐标系)。
535
+ * token 由调用方注入,缺失时抛出 MissingTokenError。
536
+ */
537
+ tianditu?: {
538
+ token: string;
539
+ type?: TiandituType;
540
+ lang?: 'zh' | 'en';
541
+ subdomains?: number[];
542
+ tileSize?: number;
543
+ maxzoom?: number;
544
+ };
368
545
  }
369
546
  /**
370
547
  * 草果地图引擎封装(展示层骨架)。
@@ -414,6 +591,8 @@ declare class Map {
414
591
  removeLayer(id: string): void;
415
592
  on(event: string, layerId?: string, cb?: (e: unknown) => void): void;
416
593
  addSource(id: string, source: object): void;
594
+ /** 安全移除 source(不存在时静默忽略) */
595
+ removeSource(id: string): void;
417
596
  getSource(id: string): unknown;
418
597
  flyTo(opts: {
419
598
  center?: [number, number];
@@ -435,6 +614,26 @@ declare class Map {
435
614
  * 返回控件实例,可调用 .toggle() / .setTheme() / .remove()。
436
615
  */
437
616
  addThemeSwitcher(initial?: ThemeName): ThemeSwitcher;
617
+ /**
618
+ * 挂载图例控件(通用):渲染数据驱动的色块/线段图例,说明专题图层语义。
619
+ * 返回控件实例,可调用 .setItems() 随图层切换更新、.remove() 卸载。
620
+ */
621
+ addLegendControl(options: {
622
+ title?: string;
623
+ items: {
624
+ label: string;
625
+ color: string;
626
+ shape?: 'color' | 'line';
627
+ }[];
628
+ }): LegendControl;
629
+ /**
630
+ * 挂载地图导出控件(通用):点击按钮将当前视图导出为 PNG 下载。
631
+ * 返回控件实例,可调用 .remove() 卸载。
632
+ */
633
+ addExportControl(options?: {
634
+ filename?: string;
635
+ buttonText?: string;
636
+ }): ExportControl;
438
637
  /**
439
638
  * 挂载辉光管线 Custom Layer(T6 / F-1.3)。
440
639
  * 传入 GeoJSON 线集合,叠加渲染管线/路网/水系辉光效果。
@@ -453,7 +652,27 @@ declare class Map {
453
652
  * @returns LodController 实例(可 .getLevel() / .remove())
454
653
  */
455
654
  addLodController<T = unknown>(levels: LodLevel<T>[], onLod: (e: LodChangeEvent<T>) => void): LodController<T>;
655
+ /**
656
+ * 启用 3D 地形渲染(F-1.5)。
657
+ *
658
+ * 注入 raster-dem 高程源并调用 maplibre-gl 原生 `setTerrain`,使地图呈现地形起伏。
659
+ * DEM 瓦片默认使用公共 Terrarium 源(elevation-tiles-prod,Terrain-RGB 编码,支持 CORS),
660
+ * 可在 opts.tiles 覆盖为私有瓦片服务(如 MinIO / 本地 MBTiles 服务)。
661
+ *
662
+ * @param opts.exaggeration 地形夸张系数(默认 1.5)
663
+ * @param opts.tiles DEM 瓦片模板,{z}/{x}/{y} 占位
664
+ * @param opts.encoding 'terrarium'(默认,Mapzen)| 'mapbox'
665
+ */
666
+ enableTerrain(opts?: {
667
+ sourceId?: string;
668
+ tiles?: string[];
669
+ encoding?: 'terrarium' | 'mapbox';
670
+ exaggeration?: number;
671
+ maxzoom?: number;
672
+ }): void;
673
+ /** 关闭 3D 地形渲染(F-1.5),并移除 DEM 源 */
674
+ disableTerrain(sourceId?: string): void;
456
675
  get instance(): Map$1;
457
676
  }
458
677
 
459
- export { type Bounds, type CRS, type CustomLayerInterface, CustomLineLayer, type GlowGeometry, type GlowLayerOptions, type GlowLine, type GlowPass, type GridShiftProvider, type LngLat, type LodChangeEvent, LodController, type LodLevel, Map, type MapInstance, type MapOptions, type Point, type ScaleBar, ScaleControl, type ScaleControlOptions, ThemeSwitcher, type ThemeSwitcherOptions, TiandituOptions, TiandituType, TileStoreBackend, type Transformer, buildGlowGeometry, cgcs2000ToWgs84, computeScaleBar, createTransformer, Map as default, fromWgs84, gcj02ToWgs84, glowPasses, isInChina, oppositeTheme, packGeoJSONToStore, projectSimple, resolveLod, setCgcs2000GridShift, suggestDensity, themeFromStyle, toWgs84, transformBounds, transformPoint, wgs84ToCgcs2000, wgs84ToGcj02 };
678
+ export { type Bounds, type CRS, type CaoguoMapGlobalConfig, type CustomLayerInterface, CustomLineLayer, ExportControl, type ExportOptions, type GlowGeometry, type GlowLayerOptions, type GlowLine, type GlowPass, type GridShiftProvider, LegendControl, type LegendItem, type LegendOptions, type LngLat, type LodChangeEvent, LodController, type LodLevel, Map, type MapInstance, type MapOptions, type MlMapSourceApi, type Point, type ScaleBar, ScaleControl, type ScaleControlOptions, ThemeSwitcher, type ThemeSwitcherOptions, TiandituOptions, TiandituType, TileStoreBackend, type Transformer, WebGLUnavailableError, buildGlowGeometry, cgcs2000ToWgs84, computeScaleBar, createTransformer, Map as default, fromWgs84, gcj02ToWgs84, getGlobalConfig, glowPasses, isInChina, isWebGLAvailable, oppositeTheme, packGeoJSONToStore, projectSimple, removeSourceSafe, removeSourcesSafe, renderLegendHtml, resolveLod, setCgcs2000GridShift, setGlobalConfig, suggestDensity, themeFromStyle, toWgs84, transformBounds, transformPoint, triggerDownload, upsertSource, wgs84ToCgcs2000, wgs84ToGcj02 };