map-ol-utils 0.2.0 → 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/dist/index.cjs CHANGED
@@ -1,1953 +1 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- //#region \0rolldown/runtime.js
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
- key = keys[i];
13
- if (!__hasOwnProp.call(to, key) && key !== except) {
14
- __defProp(to, key, {
15
- get: ((k) => from[k]).bind(null, key),
16
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
17
- });
18
- }
19
- }
20
- }
21
- return to;
22
- };
23
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
24
- value: mod,
25
- enumerable: true
26
- }) : target, mod));
27
-
28
- //#endregion
29
- const require_tile_loader = require('./tile-loader-D4cn6nMU.cjs');
30
- let ol_format_MVT_js = require("ol/format/MVT.js");
31
- ol_format_MVT_js = __toESM(ol_format_MVT_js, 1);
32
- let ol_TileState_js = require("ol/TileState.js");
33
- ol_TileState_js = __toESM(ol_TileState_js, 1);
34
- let ol_source_VectorTile_js = require("ol/source/VectorTile.js");
35
- ol_source_VectorTile_js = __toESM(ol_source_VectorTile_js, 1);
36
- let mitt = require("mitt");
37
- mitt = __toESM(mitt, 1);
38
- let ol_source_js = require("ol/source.js");
39
- let ol_layer_Tile_js = require("ol/layer/Tile.js");
40
- ol_layer_Tile_js = __toESM(ol_layer_Tile_js, 1);
41
- let ol_format_js = require("ol/format.js");
42
- let ol_source_WMTS_js = require("ol/source/WMTS.js");
43
- let ol_tilegrid_js = require("ol/tilegrid.js");
44
- let ol_layer_js = require("ol/layer.js");
45
- let ol_tilegrid_WMTS_js = require("ol/tilegrid/WMTS.js");
46
- ol_tilegrid_WMTS_js = __toESM(ol_tilegrid_WMTS_js, 1);
47
- let ol_layer_Image_js = require("ol/layer/Image.js");
48
- ol_layer_Image_js = __toESM(ol_layer_Image_js, 1);
49
- let ol_source_Raster_js = require("ol/source/Raster.js");
50
- ol_source_Raster_js = __toESM(ol_source_Raster_js, 1);
51
- let ol_Map_js = require("ol/Map.js");
52
- ol_Map_js = __toESM(ol_Map_js, 1);
53
- let ol_View_js = require("ol/View.js");
54
- ol_View_js = __toESM(ol_View_js, 1);
55
- let ol_control_js = require("ol/control.js");
56
- let gcoord = require("gcoord");
57
- gcoord = __toESM(gcoord, 1);
58
- let ol = require("ol");
59
- let ol_interaction_js = require("ol/interaction.js");
60
- let ol_extent_js = require("ol/extent.js");
61
- let ol_events_condition_js = require("ol/events/condition.js");
62
- let ol_Feature_js = require("ol/Feature.js");
63
- ol_Feature_js = __toESM(ol_Feature_js, 1);
64
- let ol_geom_Point_js = require("ol/geom/Point.js");
65
- ol_geom_Point_js = __toESM(ol_geom_Point_js, 1);
66
- let ol_layer_Vector_js = require("ol/layer/Vector.js");
67
- ol_layer_Vector_js = __toESM(ol_layer_Vector_js, 1);
68
- let ol_source_Vector_js = require("ol/source/Vector.js");
69
- ol_source_Vector_js = __toESM(ol_source_Vector_js, 1);
70
- let ol_style_js = require("ol/style.js");
71
- let ol_interaction_Draw_js = require("ol/interaction/Draw.js");
72
- ol_interaction_Draw_js = __toESM(ol_interaction_Draw_js, 1);
73
- let ol_sphere_js = require("ol/sphere.js");
74
- let ol_format_GeoJSON_js = require("ol/format/GeoJSON.js");
75
- ol_format_GeoJSON_js = __toESM(ol_format_GeoJSON_js, 1);
76
- let ol_geom_js = require("ol/geom.js");
77
- let ol_source_Cluster_js = require("ol/source/Cluster.js");
78
- ol_source_Cluster_js = __toESM(ol_source_Cluster_js, 1);
79
- let ol_style_Circle_js = require("ol/style/Circle.js");
80
- ol_style_Circle_js = __toESM(ol_style_Circle_js, 1);
81
-
82
- //#region src/core/types.ts
83
- let GeometryType = /* @__PURE__ */ function(GeometryType) {
84
- GeometryType["LineString"] = "LineString";
85
- GeometryType["MultiLineString"] = "MultiLineString";
86
- GeometryType["Polygon"] = "Polygon";
87
- GeometryType["MultiPolygon"] = "MultiPolygon";
88
- GeometryType["Invalid"] = "Invalid";
89
- return GeometryType;
90
- }({});
91
-
92
- //#endregion
93
- //#region src/tdt-vts/pk.ts
94
- const PK_DIGIT_TO_CHAR = [
95
- "a",
96
- "d",
97
- "g",
98
- "j",
99
- "m"
100
- ];
101
- const PK_CHAR_TO_DIGIT = Object.freeze({
102
- a: 0,
103
- d: 1,
104
- g: 2,
105
- j: 3,
106
- m: 4
107
- });
108
- const PERTURBED_POSITIONS = [
109
- 9,
110
- 8,
111
- 7,
112
- 6
113
- ];
114
- function assertTileInteger(name, value) {
115
- if (!Number.isSafeInteger(value) || value < 0) throw new TypeError(`${name} 必须是非负安全整数`);
116
- }
117
- /**
118
- * 将 XYZ 瓦片坐标编码为天地图 VTS 使用的 pk 参数。
119
- *
120
- * 算法按 main.0f98e6f9.js 中的实现还原:
121
- * 1. 从 bit=z 到 bit=0 交织 x/y 位;
122
- * 2. 反转;
123
- * 3. 将 0-based 位置 9、8、7、6 加一;
124
- * 4. 0/1/2/3/4 映射为 a/d/g/j/m;
125
- * 5. 连续字符使用“额外重复次数”压缩。
126
- */
127
- const encodeTdtPk = (x, y, z) => {
128
- assertTileInteger("x", x);
129
- assertTileInteger("y", y);
130
- assertTileInteger("z", z);
131
- if (z > 30) throw new RangeError("当前实现将 z 限制为 0~30;天地图底图通常不超过 18 级");
132
- const maxCoordinate = 2 ** z;
133
- if (x >= maxCoordinate || y >= maxCoordinate) throw new RangeError(`z=${z} 时 x/y 必须小于 ${maxCoordinate}`);
134
- const bigX = BigInt(x);
135
- const bigY = BigInt(y);
136
- const digits = [];
137
- for (let bit = z; bit >= 0; bit -= 1) {
138
- const mask = 1n << BigInt(bit);
139
- let digit = 0;
140
- if ((bigX & mask) !== 0n) digit |= 1;
141
- if ((bigY & mask) !== 0n) digit |= 2;
142
- digits.push(digit);
143
- }
144
- digits.reverse();
145
- for (const position of PERTURBED_POSITIONS) if (position < digits.length) {
146
- const value = digits[position];
147
- if (value === void 0) throw new Error("pk 中间状态异常");
148
- digits[position] = value + 1;
149
- }
150
- let mapped = "";
151
- for (const digit of digits) {
152
- const char = PK_DIGIT_TO_CHAR[digit];
153
- if (!char) throw new Error(`无法映射 pk 数字:${digit}`);
154
- mapped += char;
155
- }
156
- return mapped.replace(/([adgjm])\1+/g, (run) => {
157
- return `${run[0]}${run.length - 1}`;
158
- });
159
- };
160
- /** 反解 pk;用于调试、单元测试和核对网络请求。 */
161
- const decodeTdtPk = (pk) => {
162
- if (!pk) throw new TypeError("pk 不能为空");
163
- const transformed = [];
164
- let cursor = 0;
165
- while (cursor < pk.length) {
166
- const char = pk[cursor];
167
- if (!char || !(char in PK_CHAR_TO_DIGIT)) throw new Error(`pk 包含非法字符:${String(char)}`);
168
- cursor += 1;
169
- let repeatText = "";
170
- while (cursor < pk.length && /\d/.test(pk[cursor] ?? "")) {
171
- repeatText += pk[cursor];
172
- cursor += 1;
173
- }
174
- const extraRepeats = repeatText ? Number(repeatText) : 0;
175
- if (!Number.isSafeInteger(extraRepeats) || extraRepeats < 0) throw new Error(`pk 重复次数无效:${repeatText}`);
176
- const digit = PK_CHAR_TO_DIGIT[char];
177
- if (digit === void 0) throw new Error(`pk 字符无法映射:${char}`);
178
- for (let i = 0; i < extraRepeats + 1; i += 1) transformed.push(digit);
179
- }
180
- for (const position of [
181
- 6,
182
- 7,
183
- 8,
184
- 9
185
- ]) if (position < transformed.length) {
186
- const value = transformed[position];
187
- if (value === void 0) throw new Error("pk 中间状态异常");
188
- const restored = value - 1;
189
- if (restored < 0 || restored > 3) throw new Error(`pk 在位置 ${position} 的扰动值无效`);
190
- transformed[position] = restored;
191
- }
192
- const digits = transformed.reverse();
193
- const z = digits.length - 1;
194
- if (z < 0 || z > 30) throw new RangeError(`pk 推导出的 z=${z} 超出范围`);
195
- let x = 0n;
196
- let y = 0n;
197
- for (let index = 0; index < digits.length; index += 1) {
198
- const digit = digits[index];
199
- if (digit === void 0 || digit < 0 || digit > 3) throw new Error(`pk 四叉数字无效:${String(digit)}`);
200
- const bit = BigInt(z - index);
201
- if ((digit & 1) !== 0) x |= 1n << bit;
202
- if ((digit & 2) !== 0) y |= 1n << bit;
203
- }
204
- const numberX = Number(x);
205
- const numberY = Number(y);
206
- assertTileInteger("反解 x", numberX);
207
- assertTileInteger("反解 y", numberY);
208
- return {
209
- z,
210
- x: numberX,
211
- y: numberY
212
- };
213
- };
214
- /**
215
- * 根据 OpenLayers 的 [z, x, y] 生成最终 VTS 地址,不依赖字符串替换。
216
- */
217
- const createTdtVtsUrl = (tileCoord, options) => {
218
- const [z, rawX, y] = tileCoord;
219
- const { token, type = "vt", version = "1.0", maxZoom = 18, hosts = [
220
- "/tile0",
221
- "/tile1",
222
- "/tile2"
223
- ], wrapX = true } = options;
224
- if (!token || z < 0 || z > maxZoom || y < 0 || hosts.length === 0) return;
225
- const matrixSize = 2 ** z;
226
- if (y >= matrixSize) return void 0;
227
- const x = wrapX ? (rawX % matrixSize + matrixSize) % matrixSize : rawX;
228
- if (x < 0 || x >= matrixSize) return void 0;
229
- const host = hosts[Math.abs(x + y) % hosts.length];
230
- if (!host) return void 0;
231
- const params = new URLSearchParams({
232
- t: type,
233
- tk: token,
234
- v: version,
235
- pk: encodeTdtPk(x, y, z)
236
- });
237
- return `${host.replace(/\/$/, "")}/vts?${params.toString()}`;
238
- };
239
- const redactTdtToken = (url) => {
240
- try {
241
- const parsed = new URL(url);
242
- if (parsed.searchParams.has("tk")) parsed.searchParams.set("tk", "***");
243
- return parsed.toString();
244
- } catch {
245
- return url.replace(/([?&]tk=)[^&]+/i, "$1***");
246
- }
247
- };
248
-
249
- //#endregion
250
- //#region src/tdt-vts/style-loader.ts
251
- const TDT_VECTOR_SOURCE_ID = "base-tdt-vector-tile";
252
- function cloneJson(value) {
253
- return JSON.parse(JSON.stringify(value));
254
- }
255
- async function fetchJson(url, signal) {
256
- const response = await fetch(url, {
257
- mode: "cors",
258
- credentials: "omit",
259
- cache: "default",
260
- signal
261
- });
262
- if (!response.ok) throw new Error(`样式请求失败:HTTP ${response.status} ${response.statusText}`);
263
- return response.json();
264
- }
265
- function parseStyle0(value) {
266
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("style-0 不是 JSON 对象");
267
- const style = value;
268
- if (style.version !== 8) throw new Error(`style-0 version 必须为 8`);
269
- if (!style.sources || typeof style.sources !== "object") throw new Error("style-0 缺少 sources");
270
- if (!Array.isArray(style.layers)) throw new Error("style-0 缺少 layers 数组");
271
- return style;
272
- }
273
- function parseStyle1Layers(value) {
274
- if (Array.isArray(value)) return value;
275
- if (value && typeof value === "object") {
276
- const { layers } = value;
277
- if (Array.isArray(layers)) return layers;
278
- }
279
- throw new Error("style-1 必须是图层数组或带 layers 的对象");
280
- }
281
- /** 按原 bundle 的 beforeLayerId 语义逐层插入。 */
282
- const mergeTdtStyleLayers = (baseLayers, extraLayers) => {
283
- const result = baseLayers.map((layer) => cloneJson(layer));
284
- const ids = new Set(result.map((layer) => layer.id));
285
- for (const input of extraLayers) {
286
- const layer = cloneJson(input);
287
- if (!layer.id) throw new Error("style-1 存在无 id 图层");
288
- if (ids.has(layer.id)) throw new Error(`样式图层 id 重复:${layer.id}`);
289
- const beforeLayerId = typeof layer.beforeLayerId === "string" ? layer.beforeLayerId : "";
290
- delete layer.beforeLayerId;
291
- const index = beforeLayerId ? result.findIndex((candidate) => candidate.id === beforeLayerId) : -1;
292
- if (index >= 0) result.splice(index, 0, layer);
293
- else result.push(layer);
294
- ids.add(layer.id);
295
- }
296
- return result;
297
- };
298
- function resolveUrl(value, baseUrl) {
299
- try {
300
- return new URL(value, baseUrl).href;
301
- } catch {
302
- return value;
303
- }
304
- }
305
- function resolveStyleResourceUrls(style, styleUrl) {
306
- if (typeof style.glyphs === "string") style.glyphs = resolveUrl(style.glyphs, styleUrl);
307
- if (typeof style.sprite === "string") style.sprite = resolveUrl(style.sprite, styleUrl);
308
- else if (Array.isArray(style.sprite)) style.sprite = style.sprite.map((item) => {
309
- if (item && typeof item === "object" && typeof item.url === "string") return {
310
- ...item,
311
- url: resolveUrl(item.url, styleUrl)
312
- };
313
- return item;
314
- });
315
- for (const source of Object.values(style.sources)) {
316
- if (typeof source.url === "string") source.url = resolveUrl(source.url, styleUrl);
317
- if (Array.isArray(source.tiles)) source.tiles = source.tiles.map((url) => typeof url === "string" ? resolveUrl(url, styleUrl) : url);
318
- }
319
- }
320
- function removeUnsupportedLayers(layers) {
321
- const skippedLayerIds = [];
322
- return {
323
- layers: layers.filter((layer) => {
324
- if (layer.type === "pie") {
325
- skippedLayerIds.push(layer.id);
326
- return false;
327
- }
328
- return true;
329
- }),
330
- skippedLayerIds
331
- };
332
- }
333
- const loadTdtStyleBundle = async (options) => {
334
- const sourceId = options.sourceId ?? "base-tdt-vector-tile";
335
- const [raw0, raw1] = await Promise.all([fetchJson(options.style0Url, options.signal), fetchJson(options.style1Url, options.signal)]);
336
- const style0 = parseStyle0(raw0);
337
- const style1Layers = parseStyle1Layers(raw1);
338
- const style = cloneJson(style0);
339
- if (!style.sources[sourceId]) throw new Error(`style-0 中不存在 source:${sourceId}`);
340
- if (style.sources[sourceId]?.type !== "vector") throw new Error(`source ${sourceId} 不是 vector 类型`);
341
- style.layers = mergeTdtStyleLayers(style.layers, style1Layers);
342
- const filtered = removeUnsupportedLayers(style.layers);
343
- style.layers = filtered.layers;
344
- resolveStyleResourceUrls(style, options.style0Url);
345
- return {
346
- style,
347
- style0LayerCount: style0.layers.length,
348
- style1LayerCount: style1Layers.length,
349
- skippedLayerIds: filtered.skippedLayerIds
350
- };
351
- };
352
- const getConstantBackgroundColor = (style) => {
353
- for (const layer of style.layers) {
354
- if (layer.type !== "background") continue;
355
- const value = layer.paint?.["background-color"];
356
- if (typeof value === "string") return value;
357
- }
358
- };
359
-
360
- //#endregion
361
- //#region src/tdt-vts/worker-client.ts
362
- const DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
363
- const createCancellationError = (message) => {
364
- const error = new Error(message);
365
- error.name = "AbortError";
366
- return error;
367
- };
368
- var TdtDecoderWorkerClient = class {
369
- restoreMode;
370
- worker;
371
- pending = /* @__PURE__ */ new Map();
372
- nextId = 1;
373
- disposed = false;
374
- requestTimeoutMs;
375
- constructor(restoreMode, options = {}) {
376
- this.restoreMode = restoreMode;
377
- this.requestTimeoutMs = options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
378
- if (!Number.isFinite(this.requestTimeoutMs) || this.requestTimeoutMs < 0) throw new RangeError("requestTimeoutMs 必须是非负有限数");
379
- this.worker = options.workerFactory ? options.workerFactory() : new Worker(new URL("./tdt-vts/decoder.worker.mjs", require("url").pathToFileURL(__filename).href), {
380
- type: "module",
381
- name: "tdt-private-mvt-decoder"
382
- });
383
- this.worker.addEventListener("message", this.handleMessage);
384
- this.worker.addEventListener("error", this.handleWorkerError);
385
- }
386
- decode(url, options = {}) {
387
- if (this.disposed) return Promise.reject(/* @__PURE__ */ new Error("解码 Worker 已销毁"));
388
- if (options.signal?.aborted) return Promise.reject(createCancellationError("解码请求已取消"));
389
- const id = this.nextId;
390
- this.nextId += 1;
391
- return new Promise((resolve, reject) => {
392
- let timeout;
393
- const handleAbort = () => {
394
- this.cancelRequest(id, createCancellationError("解码请求已取消"));
395
- };
396
- const cleanup = () => {
397
- if (timeout !== void 0) clearTimeout(timeout);
398
- options.signal?.removeEventListener("abort", handleAbort);
399
- };
400
- this.pending.set(id, {
401
- resolve,
402
- reject,
403
- cleanup
404
- });
405
- options.signal?.addEventListener("abort", handleAbort, { once: true });
406
- if (this.requestTimeoutMs > 0) timeout = setTimeout(() => {
407
- this.cancelRequest(id, /* @__PURE__ */ new Error("解码请求超时"));
408
- }, this.requestTimeoutMs);
409
- const request = {
410
- type: "decode-tile",
411
- id,
412
- url,
413
- restoreMode: this.restoreMode
414
- };
415
- try {
416
- this.worker.postMessage(request);
417
- } catch (cause) {
418
- this.takePending(id)?.reject(cause instanceof Error ? cause : new Error(String(cause)));
419
- }
420
- });
421
- }
422
- dispose() {
423
- if (this.disposed) return;
424
- this.disposed = true;
425
- this.worker.removeEventListener("message", this.handleMessage);
426
- this.worker.removeEventListener("error", this.handleWorkerError);
427
- this.worker.terminate();
428
- const error = /* @__PURE__ */ new Error("解码 Worker 已销毁");
429
- for (const request of this.pending.values()) {
430
- request.cleanup();
431
- request.reject(error);
432
- }
433
- this.pending.clear();
434
- }
435
- takePending(id) {
436
- const pending = this.pending.get(id);
437
- if (!pending) return void 0;
438
- this.pending.delete(id);
439
- pending.cleanup();
440
- return pending;
441
- }
442
- cancelRequest(id, error) {
443
- const pending = this.takePending(id);
444
- if (!pending) return;
445
- const request = {
446
- type: "cancel-tile",
447
- id
448
- };
449
- try {
450
- this.worker.postMessage(request);
451
- } catch {}
452
- pending.reject(error);
453
- }
454
- fail(error) {
455
- if (this.disposed) return;
456
- this.disposed = true;
457
- this.worker.removeEventListener("message", this.handleMessage);
458
- this.worker.removeEventListener("error", this.handleWorkerError);
459
- this.worker.terminate();
460
- for (const request of this.pending.values()) {
461
- request.cleanup();
462
- request.reject(error);
463
- }
464
- this.pending.clear();
465
- }
466
- handleMessage = (event) => {
467
- const response = event.data;
468
- if (response.type !== "decode-result") return;
469
- const pending = this.takePending(response.id);
470
- if (!pending) return;
471
- if (response.ok) pending.resolve({
472
- buffer: response.buffer,
473
- stats: response.stats
474
- });
475
- else pending.reject(new Error(response.error));
476
- };
477
- handleWorkerError = (event) => {
478
- const error = new Error(event.message || "解码 Worker 发生未捕获错误");
479
- this.fail(error);
480
- };
481
- };
482
-
483
- //#endregion
484
- //#region src/tdt-vts/source.ts
485
- const createTdtVectorSource = (options) => {
486
- const decoder = new TdtDecoderWorkerClient(options.restoreMode, options.decoderOptions);
487
- const format = new ol_format_MVT_js.default({ layerName: "mvt:layer" });
488
- const source = new ol_source_VectorTile_js.default({
489
- projection: "EPSG:3857",
490
- minZoom: options.minZoom ?? 1,
491
- maxZoom: options.maxZoom ?? 18,
492
- tileSize: 512,
493
- wrapX: true,
494
- format,
495
- attributions: "© <a href=\"https://www.tianditu.gov.cn/\" target=\"_blank\" rel=\"noopener\">天地图</a>",
496
- tileUrlFunction(tileCoord) {
497
- if (!tileCoord) return void 0;
498
- const [z, x, y] = tileCoord;
499
- if (z === void 0 || x === void 0 || y === void 0) return void 0;
500
- return createTdtVtsUrl([
501
- z,
502
- x,
503
- y
504
- ], {
505
- token: options.token,
506
- maxZoom: options.maxZoom ?? 18,
507
- wrapX: true
508
- });
509
- },
510
- tileLoadFunction(tile, url) {
511
- const vectorTile = tile;
512
- vectorTile.setLoader(async (extent, _resolution, projection) => {
513
- const redactedUrl = redactTdtToken(url);
514
- try {
515
- const decoded = await decoder.decode(url);
516
- const features = format.readFeatures(decoded.buffer, {
517
- extent,
518
- featureProjection: projection
519
- });
520
- vectorTile.setFeatures(features);
521
- options.diagnostics?.onDecoded?.(decoded.stats, redactedUrl);
522
- } catch (cause) {
523
- const error = cause instanceof Error ? cause : new Error(String(cause));
524
- options.diagnostics?.onError?.(error, redactedUrl);
525
- console.error("天地图私有 VTS 加载失败", redactedUrl, error);
526
- vectorTile.setState(ol_TileState_js.default.ERROR);
527
- }
528
- });
529
- }
530
- });
531
- const disposeSource = source.dispose.bind(source);
532
- source.dispose = () => {
533
- decoder.dispose();
534
- disposeSource();
535
- };
536
- return {
537
- source,
538
- decoder
539
- };
540
- };
541
-
542
- //#endregion
543
- //#region src/core/emitter.ts
544
- const emitter = (0, mitt.default)();
545
-
546
- //#endregion
547
- //#region src/core/map-context.ts
548
- /** 当前 OpenLayers 单例。集中存放以避免业务模块之间互相引用。 */
549
- let instance;
550
- /** @internal 更新当前地图单例。 */
551
- const setMapInstance = (map) => {
552
- instance = map;
553
- };
554
- /** @internal 清空当前地图单例。 */
555
- const clearMapInstance = () => {
556
- instance = void 0;
557
- };
558
-
559
- //#endregion
560
- //#region src/core/helper.ts
561
- const hexToRgba = (hex, alpha) => {
562
- if (hex.startsWith("#")) {
563
- let tempHex = hex.replace("#", "");
564
- if (tempHex.length === 3) tempHex = tempHex[0] + tempHex[0] + tempHex[1] + tempHex[1] + tempHex[2] + tempHex[2];
565
- return `rgba(${parseInt(tempHex.substring(0, 2), 16)}, ${parseInt(tempHex.substring(2, 4), 16)}, ${parseInt(tempHex.substring(4, 6), 16)}, ${alpha})`;
566
- } else return hex;
567
- };
568
- const getLayersDataList = () => instance?.getAllLayers().map((layer) => layer.get("_dataList") || []).flat(2) || [];
569
- const determineGeometryType = (coordinates) => {
570
- const getArrayDepth = (arr) => {
571
- if (!Array.isArray(arr) || arr.length === 0) return 0;
572
- return 1 + getArrayDepth(arr[0]);
573
- };
574
- const isClosedRing = (coords) => {
575
- if (!Array.isArray(coords) || coords.length < 3) return false;
576
- const first = coords[0];
577
- const last = coords[coords.length - 1];
578
- return first[0] === last[0] && first[1] === last[1];
579
- };
580
- const isValidCoordinate = (coord) => {
581
- return Array.isArray(coord) && coord.length >= 2 && typeof coord[0] === "number" && typeof coord[1] === "number";
582
- };
583
- const isValidLineString = (coords) => {
584
- return Array.isArray(coords) && coords.length >= 2 && coords.every(isValidCoordinate);
585
- };
586
- const isValidPolygon = (coords) => {
587
- if (!Array.isArray(coords)) return false;
588
- return (getArrayDepth(coords) === 2 ? [coords] : coords).every((ring) => Array.isArray(ring) && ring.length >= 4 && isClosedRing(ring) && ring.every(isValidCoordinate));
589
- };
590
- const depth = getArrayDepth(coordinates);
591
- try {
592
- if (depth < 2 || !coordinates || coordinates.length === 0) return "Invalid";
593
- else if (depth === 2 && isValidLineString(coordinates)) return isClosedRing(coordinates) && coordinates.length >= 4 ? "Polygon" : "LineString";
594
- else if (depth === 3 && Array.isArray(coordinates) && coordinates.every(isValidLineString)) {
595
- if (isValidPolygon(coordinates)) return "Polygon";
596
- else if (coordinates.every((arr) => !isClosedRing(arr))) return "MultiLineString";
597
- else return "Invalid";
598
- } else if (depth === 4 && Array.isArray(coordinates) && coordinates.every((rings) => isValidPolygon(rings))) return "MultiPolygon";
599
- else return "Invalid";
600
- } catch (error) {
601
- console.error("Error analyzing coordinates:", error);
602
- return "Invalid";
603
- }
604
- };
605
-
606
- //#endregion
607
- //#region src/layer/ogc-utils.ts
608
- const parser = new ol_format_js.WMTSCapabilities();
609
- const capabilitiesMap = /* @__PURE__ */ new Map();
610
- const getCapabilities = (url) => {
611
- return new Promise((resolve) => {
612
- const capabilities = capabilitiesMap.get(url);
613
- if (capabilities) resolve(capabilities);
614
- else fetch(url).then((data) => data.text()).then((text) => {
615
- const capabilities = parser.read(text);
616
- capabilitiesMap.set(url, capabilities);
617
- resolve(capabilities);
618
- });
619
- });
620
- };
621
- /**
622
- * 创建WMTS图层
623
- * @param serverUrl
624
- */
625
- const createWmtsLayer = (serverUrl) => async (config) => {
626
- const { style, format, version, layerName, matrixSet } = config;
627
- const [workspace, datastore] = layerName.split(":");
628
- const capabilitiesUrl = `${serverUrl}/${workspace}/${datastore}/gwc/service/wmts?request=GetCapabilities`;
629
- return new Promise((resolve, reject) => {
630
- getCapabilities(capabilitiesUrl).then((data) => {
631
- const options = (0, ol_source_WMTS_js.optionsFromCapabilities)(data, {
632
- Style: style || "",
633
- layer: datastore,
634
- version: version || "1.1.0",
635
- format: format || "image/png",
636
- matrixSet: matrixSet || "EPSG:4326"
637
- });
638
- if (options) resolve(new ol_layer_Tile_js.default({
639
- zIndex: 3,
640
- className: layerName,
641
- source: new ol_source_js.WMTS(options)
642
- }));
643
- else reject(/* @__PURE__ */ new Error("Unable to create TileLayer"));
644
- });
645
- });
646
- };
647
-
648
- //#endregion
649
- //#region src/core/constants.ts
650
- /**
651
- * 天地图默认访问令牌(仅作缺省值,正式项目请通过参数 / config 覆盖)
652
- */
653
- const DEFAULT_TIANDITU_TK = "c77eddc667c5bed016fded560baf93e7";
654
- /**
655
- * 浙江省天地图默认访问令牌(仅作缺省值,正式项目请通过参数覆盖)
656
- */
657
- const DEFAULT_ZHEJIANG_TOKEN = "3b0cdd02-c366-4363-b6de-081a9f12b364";
658
-
659
- //#endregion
660
- //#region src/layer/layer-lifecycle.ts
661
- /** @internal 从地图移除图层并释放其数据源与自身资源。 */
662
- const disposeLayer = (map, layer) => {
663
- const dynamicMarkerTimer = layer.get("_dynamicMarkerTimer");
664
- if (dynamicMarkerTimer !== void 0) {
665
- clearTimeout(dynamicMarkerTimer);
666
- layer.unset("_dynamicMarkerTimer");
667
- }
668
- layer.getSource()?.dispose();
669
- map.removeLayer(layer);
670
- layer.dispose();
671
- };
672
-
673
- //#endregion
674
- //#region src/layer/base-layer.ts
675
- /**
676
- * 创建杭州规自地图
677
- * @param layerName - 'hzsyraster' | 'hzsyvector' | 'hzsyvector_dark'
678
- */
679
- const createBaseLayer = (layerName = "hzsyvector_dark") => {
680
- const config = {
681
- zIndex: -5,
682
- preload: 1,
683
- minZoom: 8,
684
- maxZoom: 21,
685
- source: new ol_source_js.XYZ({
686
- tileGrid: new ol_tilegrid_js.TileGrid({
687
- tileSize: 256,
688
- resolutions: [
689
- .00549933137253187,
690
- .00274966568626595,
691
- .00137483284313297,
692
- .000687416421566485,
693
- .000343708210783242,
694
- .000171854105391621,
695
- 859270526958104e-19,
696
- 429635263479052e-19,
697
- 214817631739526e-19,
698
- 107408815869763e-19,
699
- 537044079348816e-20,
700
- 268522039674407e-20,
701
- 134261019837204e-20
702
- ],
703
- origin: [118.122911693886, 31.2869311022836],
704
- extent: [
705
- 116.43263049006,
706
- 28.6201742126026,
707
- 123.705594256347,
708
- 31.9765041681924
709
- ]
710
- }),
711
- projection: "EPSG:4326",
712
- urls: [
713
- `https://ywtg.citybrain.hangzhou.gov.cn/${layerName}/{z}/{y}/{x}`,
714
- `https://ywtg.citybrain.hangzhou.gov.cn:9456/${layerName}/{z}/{y}/{x}`,
715
- `https://ywtg.citybrain.hangzhou.gov.cn:9457/${layerName}/{z}/{y}/{x}`,
716
- `https://ywtg.citybrain.hangzhou.gov.cn:9458/${layerName}/{z}/{y}/{x}`,
717
- `https://ywtg.citybrain.hangzhou.gov.cn:9459/${layerName}/{z}/{y}/{x}`
718
- ]
719
- }),
720
- properties: {
721
- _isBaseLayer: true,
722
- _layerName: layerName
723
- }
724
- };
725
- return new ol_layer_js.Tile(config);
726
- };
727
- /**
728
- * 创建全国天地图
729
- * @param layerName - 图层名称
730
- * @param tk - 天地图TK
731
- */
732
- const createMapWorldLayer = (layerName, tk = DEFAULT_TIANDITU_TK) => {
733
- const [name, matrixSet] = layerName.split("_");
734
- const config = {
735
- preload: 1,
736
- zIndex: -10,
737
- cacheSize: 20240,
738
- properties: {
739
- _isBaseLayer: true,
740
- _layerName: layerName
741
- },
742
- source: new ol_source_js.WMTS({
743
- crossOrigin: "anonymous",
744
- projection: "EPSG:4326",
745
- wrapX: true,
746
- layer: name,
747
- style: "default",
748
- version: "1.0.0",
749
- format: "image/png",
750
- matrixSet,
751
- tileGrid: new ol_tilegrid_WMTS_js.default({
752
- tileSize: 256,
753
- origin: [-180, 90],
754
- matrixIds: [
755
- "1",
756
- "2",
757
- "3",
758
- "4",
759
- "5",
760
- "6",
761
- "7",
762
- "8",
763
- "9",
764
- "10",
765
- "11",
766
- "12",
767
- "13",
768
- "14",
769
- "15",
770
- "16",
771
- "17",
772
- "18",
773
- "19"
774
- ],
775
- resolutions: [
776
- .703125,
777
- .3515625,
778
- .17578125,
779
- .087890625,
780
- .0439453125,
781
- .02197265625,
782
- .010986328125,
783
- .0054931640625,
784
- .00274658203125,
785
- .001373291015625,
786
- .0006866455078125,
787
- .00034332275390625,
788
- .000171661376953125,
789
- 858306884765625e-19,
790
- 4291534423828125e-20,
791
- 21457672119140625e-21,
792
- 10728836059570312e-21,
793
- 5364418029785156e-21,
794
- 2682209014892578e-21
795
- ]
796
- }),
797
- url: `https://t{0-7}.tianditu.gov.cn/${layerName}/wmts?tk=${tk}`
798
- })
799
- };
800
- return new ol_layer_js.Tile(config);
801
- };
802
- /**
803
- * 创建天地图矢量/影像底图组合。
804
- * @param tk - 天地图访问令牌
805
- */
806
- const baseLayers = (tk) => ({
807
- baseImgLayer: new ol_layer_js.Tile({
808
- className: "img-layer",
809
- source: new ol_source_js.XYZ({
810
- crossOrigin: "anonymous",
811
- tileSize: 256,
812
- url: `https://t{0-7}.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=${tk}`
813
- }),
814
- zIndex: 1
815
- }),
816
- baseCiaLayer: new ol_layer_js.Tile({
817
- className: "img-layer",
818
- source: new ol_source_js.XYZ({
819
- crossOrigin: "anonymous",
820
- tileSize: 256,
821
- url: `https://t{0-7}.tianditu.gov.cn/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=${tk}`
822
- }),
823
- zIndex: 2
824
- }),
825
- baseVecLayer: new ol_layer_js.Tile({
826
- className: "vec-layer",
827
- source: new ol_source_js.XYZ({
828
- crossOrigin: "anonymous",
829
- tileSize: 256,
830
- url: `https://t{0-7}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=${tk}`
831
- }),
832
- zIndex: 1
833
- }),
834
- baseCvaLayer: new ol_layer_js.Tile({
835
- className: "vec-layer",
836
- source: new ol_source_js.XYZ({
837
- crossOrigin: "anonymous",
838
- tileSize: 256,
839
- url: `https://t{0-7}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=${tk}`
840
- }),
841
- zIndex: 2
842
- })
843
- });
844
- /**
845
- * 浙江省天地图
846
- * @param layerName - 图层名称
847
- * @param tk -
848
- */
849
- const createZheJiangLayer = (layerName = "emap", tk = DEFAULT_ZHEJIANG_TOKEN) => {
850
- return new ol_layer_js.Tile({
851
- preload: 1,
852
- minZoom: 4,
853
- maxZoom: 20,
854
- zIndex: -10,
855
- cacheSize: 20240,
856
- source: new ol_source_js.XYZ({
857
- wrapX: true,
858
- projection: "EPSG:4326",
859
- crossOrigin: "anonymous",
860
- url: `https://ditu{0-6}.zjzwfw.gov.cn/services/wmts/${layerName}/default/oss/getTile/{z}/{y}/{x}?token=${tk}`
861
- })
862
- });
863
- };
864
- /**
865
- * 根据图层名称获取图层
866
- * @param name
867
- */
868
- const getLayerByName = (name) => instance.getAllLayers().find((item) => (item.get("_layerName") || item.getClassName()) === name);
869
- /**
870
- * 根据图层名称删除图层
871
- * @param name
872
- */
873
- const removeLayerByName = (name) => {
874
- const layer = getLayerByName(name);
875
- if (layer) disposeLayer(instance, layer);
876
- };
877
- /**
878
- * 切换图层的显示、隐藏
879
- * @param activeNames
880
- * @param allLayerNames
881
- */
882
- const changeLayersByNames = (activeNames, allLayerNames) => {
883
- instance.getAllLayers().filter((item) => allLayerNames.includes(item.getClassName())).forEach((layer) => {
884
- layer.setVisible(activeNames?.includes(layer.getClassName()));
885
- });
886
- };
887
-
888
- //#endregion
889
- //#region src/layer/raster-layer.ts
890
- const getDefaultThreadCount = () => Math.max(1, Math.min(4, globalThis.navigator?.hardwareConcurrency ?? 2));
891
- /** 使用 RGB 比例和目标颜色转换栅格图层。 */
892
- const changeSource = (layer, rgbColorArray, ratioArray, options = {}) => {
893
- const rasterSource = new ol_source_Raster_js.default({
894
- sources: [layer],
895
- operationType: "image",
896
- operation: (pixels, data) => {
897
- const reverseFunc = (pixelArray, operationData) => {
898
- const operationRatioArray = operationData.ratioArray;
899
- const operationRgbColorArray = operationData.rgbColorArray;
900
- if (operationRatioArray && operationRgbColorArray) {
901
- const [redRatio = 0, greenRatio = 0, blueRatio = 0] = operationRatioArray;
902
- for (let index = 0; index < pixelArray.length; index += 4) {
903
- const red = pixelArray[index];
904
- const green = pixelArray[index + 1];
905
- const blue = pixelArray[index + 2];
906
- const grey = red * redRatio + green * greenRatio + blue * blueRatio;
907
- pixelArray[index] = operationRgbColorArray[0] - grey;
908
- pixelArray[index + 1] = operationRgbColorArray[1] - grey;
909
- pixelArray[index + 2] = operationRgbColorArray[2] - grey;
910
- }
911
- }
912
- };
913
- reverseFunc(pixels[0].data, data);
914
- return pixels[0];
915
- },
916
- threads: options.threads ?? getDefaultThreadCount()
917
- });
918
- rasterSource.on("beforeoperations", (event) => {
919
- event.data.ratioArray = ratioArray;
920
- event.data.rgbColorArray = rgbColorArray;
921
- });
922
- return rasterSource;
923
- };
924
- /** 使用 changeSource 创建可显示的 VectorImageLayer。 */
925
- const changeLayer = (layer, rgbColorArray, ratioArray, options = {}) => new ol_layer_Image_js.default({ source: changeSource(layer, rgbColorArray, ratioArray, options) });
926
-
927
- //#endregion
928
- //#region src/overlay/overlay.ts
929
- /**
930
- * 移除带指定属性键的 Overlay(默认按 'position')
931
- * @param key
932
- */
933
- const removeOverlays = (key = "") => {
934
- if (instance) instance.getOverlays().getArray().filter((overlay) => overlay.get(key || "position")).forEach((overlay) => instance.removeOverlay(overlay));
935
- };
936
- const removeAnimationMarker = () => removeOverlays("_isAnimationMarker");
937
- /**
938
- * 创建动画标注 Overlay
939
- * @param imgUrl
940
- * @param data
941
- */
942
- const createAnimationMarker = (imgUrl, data) => {
943
- removeAnimationMarker();
944
- const { width, height, lnglat, crsForm } = data;
945
- const element = document.createElement("div");
946
- const image = document.createElement("img");
947
- image.src = imgUrl;
948
- image.alt = "";
949
- if (width !== void 0) image.width = width;
950
- if (height !== void 0) image.height = height;
951
- element.append(image);
952
- const overlay = new ol.Overlay({
953
- element,
954
- stopEvent: false,
955
- positioning: "bottom-center",
956
- position: gcoord.default.transform([+lnglat[0], +lnglat[1]], crsForm || gcoord.default.WGS84, gcoord.default.WGS84)
957
- });
958
- overlay.set("_isAnimationMarker", true);
959
- instance.addOverlay(overlay);
960
- };
961
- /**
962
- * 创建 Overlay
963
- * @param config
964
- */
965
- const createOverlay = (config = {
966
- id: "popup-container",
967
- positioning: "top-center"
968
- }) => {
969
- return new ol.Overlay(Object.assign({ element: document.getElementById(config.id) || void 0 }, config));
970
- };
971
-
972
- //#endregion
973
- //#region src/layer/layer-manager.ts
974
- /**
975
- * 重置激活的矢量数据(清空 overlay 与各图层选择交互的要素集合)
976
- */
977
- const resetActiveVector = () => {
978
- removeOverlays();
979
- instance.getAllLayers().forEach((layer) => {
980
- layer.get("_selectInteraction")?.getFeatures().clear();
981
- });
982
- };
983
- /**
984
- * 移除覆盖物以及所有非底图自定义图层
985
- */
986
- const removeAllLayers = () => {
987
- removeOverlays();
988
- if (instance) instance.getAllLayers().forEach((layer) => {
989
- if (!layer.get("_isBaseLayer")) disposeLayer(instance, layer);
990
- });
991
- };
992
- /**
993
- * 重置激活 Feature
994
- */
995
- const resetActiveFeature = () => {
996
- removeOverlays();
997
- instance.getAllLayers().filter((layer) => layer.get("_isVectorLayer")).forEach((layer) => {
998
- const selectInteraction = layer.get("_selectInteraction");
999
- if (selectInteraction) {
1000
- selectInteraction.dispatchEvent({
1001
- type: "select",
1002
- selected: [],
1003
- mapBrowserEvent: void 0,
1004
- deselected: selectInteraction.getFeatures().getArray()
1005
- });
1006
- selectInteraction.getFeatures().clear();
1007
- }
1008
- });
1009
- };
1010
- /**
1011
- * 按 _uuid 激活要素
1012
- * @param uid
1013
- */
1014
- const activeFeatureByUid = (uid) => {
1015
- const targetLayers = instance.getAllLayers().filter((layer) => layer.get("_isVectorLayer"));
1016
- if (targetLayers.length) {
1017
- const targetLayer = targetLayers.find((layer) => layer.get("_uuidSet").has(uid) && layer.get("_selectInteraction"));
1018
- if (targetLayer) {
1019
- const targetFeature = (targetLayer.getSource()?.getFeatures() || []).find((feature) => feature.get("_uuid") === uid);
1020
- const selectInteraction = targetLayer.get("_selectInteraction");
1021
- if (selectInteraction) {
1022
- const collection = selectInteraction.getFeatures().getArray();
1023
- if (!collection.find((feature) => feature.get("_uuid") === uid)) {
1024
- selectInteraction.dispatchEvent({
1025
- type: "select",
1026
- deselected: collection,
1027
- selected: [targetFeature],
1028
- mapBrowserEvent: void 0
1029
- });
1030
- selectInteraction.getFeatures().push(targetFeature);
1031
- }
1032
- }
1033
- }
1034
- }
1035
- };
1036
-
1037
- //#endregion
1038
- //#region src/map/create-map.ts
1039
- let mapCenter = [119.71512016971076, 30.122490541963536];
1040
- const createMapInstance = (config = {}) => {
1041
- if (instance) return instance;
1042
- const map = createMap(config);
1043
- setMapInstance(map);
1044
- return map;
1045
- };
1046
- const createMap = (config = {}) => {
1047
- const innerConfig = Object.assign({
1048
- zoom: 9.4,
1049
- maxZoom: 18,
1050
- minZoom: 9.4,
1051
- center: mapCenter,
1052
- baseLayer: "vec-layer",
1053
- projection: "EPSG:4326",
1054
- layers: [createBaseLayer()],
1055
- constrainResolution: false,
1056
- smoothExtentConstraint: false,
1057
- tk: DEFAULT_TIANDITU_TK
1058
- }, config || {});
1059
- const map = new ol_Map_js.default({
1060
- view: new ol_View_js.default(innerConfig),
1061
- controls: (0, ol_control_js.defaults)({
1062
- zoom: false,
1063
- rotate: false,
1064
- attribution: false
1065
- }),
1066
- interactions: (0, ol_interaction_js.defaults)({
1067
- pinchRotate: false,
1068
- doubleClickZoom: false,
1069
- altShiftDragRotate: false
1070
- }),
1071
- layers: innerConfig.layers || [createBaseLayer()]
1072
- });
1073
- mapCenter = innerConfig.center || mapCenter;
1074
- map.activeBaseLayer = innerConfig.baseLayer;
1075
- map.getLayerByName = getLayerByName;
1076
- map.removeLayerByName = removeLayerByName;
1077
- map.changeLayersByNames = changeLayersByNames;
1078
- let pointerMoveFrame;
1079
- let latestPixel;
1080
- const cancelPointerMoveFrame = () => {
1081
- if (pointerMoveFrame === void 0) return;
1082
- if (typeof globalThis.cancelAnimationFrame === "function") globalThis.cancelAnimationFrame(pointerMoveFrame);
1083
- else clearTimeout(pointerMoveFrame);
1084
- pointerMoveFrame = void 0;
1085
- };
1086
- map.on("pointermove", (evt) => {
1087
- latestPixel = evt.pixel;
1088
- if (pointerMoveFrame !== void 0) return;
1089
- const updateCursor = () => {
1090
- pointerMoveFrame = void 0;
1091
- if (!latestPixel) return;
1092
- map.getTargetElement().style.cursor = map.hasFeatureAtPixel(latestPixel) ? "pointer" : "";
1093
- };
1094
- pointerMoveFrame = typeof globalThis.requestAnimationFrame === "function" ? globalThis.requestAnimationFrame(updateCursor) : setTimeout(updateCursor, 16);
1095
- });
1096
- map.set("_disposePointerMove", cancelPointerMoveFrame);
1097
- return map;
1098
- };
1099
- const disposeMap = () => {
1100
- if (!instance) return;
1101
- const map = instance;
1102
- map.get("_disposePointerMove")?.();
1103
- map.unset("_disposePointerMove");
1104
- map.getOverlays().forEach((overlay) => {
1105
- map.removeOverlay(overlay);
1106
- });
1107
- map.getInteractions().clear();
1108
- map.getAllLayers().forEach((layer) => disposeLayer(map, layer));
1109
- map.setTarget("");
1110
- map.dispose();
1111
- clearMapInstance();
1112
- };
1113
- /** 兼容别名;复用 map-ol-utils 现有的完整销毁语义。 */
1114
- const disposeInstance = () => disposeMap();
1115
- const getMapInstance = () => instance;
1116
- const resetZoomAndCenter = (center = mapCenter) => {
1117
- if (instance) instance.getView().animate({
1118
- zoom: 9.4,
1119
- center,
1120
- duration: 1e3
1121
- });
1122
- };
1123
- const resetMap = (config = {
1124
- center: mapCenter,
1125
- isClearAll: true
1126
- }) => {
1127
- removeAllLayers();
1128
- resetZoomAndCenter(config.center || mapCenter);
1129
- };
1130
-
1131
- //#endregion
1132
- //#region src/map/view-fit.ts
1133
- /** 视野自适应的默认参数(padding + 动画时长) */
1134
- const DEFAULT_FIT_OPTIONS = {
1135
- padding: [
1136
- 50,
1137
- 50,
1138
- 50,
1139
- 50
1140
- ],
1141
- duration: 1e3
1142
- };
1143
- /**
1144
- * 根据 Array<Coordinate> Fit
1145
- * @param coords
1146
- * @param mapInstance
1147
- * @param fitOptions
1148
- */
1149
- const setFitViewByCoords = (coords, mapInstance = instance, fitOptions) => {
1150
- const view = mapInstance.getView();
1151
- if (coords.length === 1) view.animate({
1152
- zoom: 14,
1153
- duration: 1e3,
1154
- center: coords[0],
1155
- ...fitOptions || {}
1156
- });
1157
- else {
1158
- const extent = (0, ol_extent_js.boundingExtent)(coords);
1159
- view.fit(extent, {
1160
- ...DEFAULT_FIT_OPTIONS,
1161
- ...fitOptions || {}
1162
- });
1163
- }
1164
- };
1165
- /**
1166
- * 根据 SimpleGeometry Fit
1167
- * @param geom
1168
- * @param mapInstance
1169
- * @param fitOptions
1170
- */
1171
- const setFitViewByGeom = (geom, mapInstance = instance, fitOptions) => {
1172
- mapInstance.getView().fit(geom, {
1173
- ...DEFAULT_FIT_OPTIONS,
1174
- ...fitOptions || {}
1175
- });
1176
- };
1177
- /**
1178
- * 根据 VectorLayer 要素的四至信息 Fit
1179
- * @param layer
1180
- * @param mapInstance
1181
- * @param fitOptions
1182
- */
1183
- const setFitViewByLayer = (layer, mapInstance = instance, fitOptions) => {
1184
- const source = layer.getSource();
1185
- if (!source || source.isEmpty()) return;
1186
- const extent = source.getExtent();
1187
- mapInstance.getView().fit(extent, {
1188
- ...DEFAULT_FIT_OPTIONS,
1189
- ...fitOptions || {}
1190
- });
1191
- };
1192
- /** 使用两段缩放动画飞到目标位置。 */
1193
- const flyToAnimate = (center, zoom) => {
1194
- const view = instance.getView();
1195
- const currentZoom = view.getZoom();
1196
- view.animate({
1197
- center,
1198
- duration: 2e3
1199
- });
1200
- if (!zoom) view.animate({
1201
- zoom: currentZoom - 2,
1202
- duration: 1e3
1203
- }, {
1204
- zoom: currentZoom + 2 > 12 ? 12 : currentZoom + 2,
1205
- duration: 1e3
1206
- });
1207
- else view.animate({
1208
- zoom: zoom - 2,
1209
- duration: 1e3
1210
- }, {
1211
- zoom,
1212
- duration: 1e3
1213
- });
1214
- };
1215
-
1216
- //#endregion
1217
- //#region src/layer/marker-layer.ts
1218
- /** 创建 Marker 文本标注。 */
1219
- const createText = (item) => new ol_style_js.Text({
1220
- text: item.text,
1221
- offsetY: item.offsetY,
1222
- offsetX: item.offsetX,
1223
- justify: "center",
1224
- textAlign: "center",
1225
- font: "16px PingFangSC-Semibold",
1226
- fill: new ol_style_js.Fill({ color: "rgba(255, 255, 255, 0.8)" })
1227
- });
1228
- /** 创建 Marker 默认态或激活态样式。 */
1229
- const createIconStyle = (item, active = false) => new ol_style_js.Style({
1230
- image: new ol_style_js.Icon({
1231
- scale: item.scale || 1,
1232
- rotation: item.rotation || 0,
1233
- anchor: item.anchor || [.5, 1],
1234
- src: active ? item.activeImg || item.img : item.img
1235
- }),
1236
- text: item.showText ? createText(item) : void 0
1237
- });
1238
- /** 创建带 data 属性约定的 Marker Feature。 */
1239
- const createMarker = (item, config) => {
1240
- const feature = new ol_Feature_js.default({
1241
- geometry: new ol_geom_Point_js.default([+item.lng, +item.lat]),
1242
- data: Object.assign({}, item || {}, { layerName: config.layerName })
1243
- });
1244
- feature.setStyle(createIconStyle(item));
1245
- return feature;
1246
- };
1247
- /** 批量创建 Marker 矢量图层。 */
1248
- const createMarkersLayer = (dataList, config) => {
1249
- const { layerName, visible = true, zIndex = 10 } = config;
1250
- const source = new ol_source_Vector_js.default();
1251
- dataList.forEach((item) => source.addFeature(createMarker(item, config)));
1252
- return new ol_layer_Vector_js.default({
1253
- zIndex,
1254
- visible,
1255
- source,
1256
- className: layerName || "marker-layer"
1257
- });
1258
- };
1259
- /** @internal 按当前缩放级别刷新弹性 Marker 的图标。 */
1260
- const setElasticMarkerStyle = (featureList, currentZoom) => {
1261
- const imageKey = currentZoom >= 14 ? "largeImg" : currentZoom >= 11 ? "smallImg" : "img";
1262
- featureList.forEach((feature) => {
1263
- const config = feature.get("data");
1264
- if (!config.isSelected) feature.setStyle(createIconStyle({
1265
- ...config,
1266
- img: config[imageKey]
1267
- }, false));
1268
- });
1269
- };
1270
- /** @internal 同步 Marker 选中状态及对应图标样式。 */
1271
- const setMarkerSelectedState = (feature, selected) => {
1272
- const config = feature.get("data");
1273
- const next = {
1274
- ...config,
1275
- isSelected: selected
1276
- };
1277
- feature.set("data", next);
1278
- if (config.isElastic) setElasticMarkerStyle([feature], instance.getView().getZoom());
1279
- else feature.setStyle(createIconStyle(next, selected));
1280
- };
1281
- /** 清空外部选择集合并恢复 Marker 未选中样式。 */
1282
- const changeUnselectStyle = (featureList) => {
1283
- featureList.forEach((feature) => {
1284
- setMarkerSelectedState(feature, false);
1285
- });
1286
- featureList.clear();
1287
- };
1288
- /** 创建随缩放级别切换小图/大图的 Marker 图层。 */
1289
- const createElasticMarkerLayer = (dataList, config) => {
1290
- const elasticData = dataList.map((item) => ({
1291
- ...item,
1292
- isElastic: true
1293
- }));
1294
- const vectorLayer = createMarkersLayer(elasticData, config);
1295
- const features = vectorLayer.getSource().getFeatures();
1296
- setElasticMarkerStyle(features, instance.getView().getZoom());
1297
- instance.getView().on("change:resolution", ({ target }) => {
1298
- setElasticMarkerStyle(features, target.get("zoom"));
1299
- });
1300
- return vectorLayer;
1301
- };
1302
- /** 创建单 Marker 图层并直接加入当前地图实例。 */
1303
- const createMoveMarkerLayer = (dataItem, config) => {
1304
- const marker = createMarker(dataItem, config);
1305
- const vectorLayer = new ol_layer_Vector_js.default({
1306
- className: config.layerName || "ol-layer",
1307
- source: new ol_source_Vector_js.default({ features: [marker] })
1308
- });
1309
- instance.addLayer(vectorLayer);
1310
- return { vectorLayer };
1311
- };
1312
-
1313
- //#endregion
1314
- //#region src/interaction/select.ts
1315
- /**
1316
- * 处理要素选中:切换激活样式、派发事件、按需自动居中
1317
- * @param vectorLayer
1318
- * @param feature
1319
- */
1320
- const selectEventHandle = (vectorLayer, feature) => {
1321
- const data = feature.getProperties();
1322
- const { activeStyle } = data;
1323
- feature.setStyle(activeStyle);
1324
- emitter.emit("selected-feature", data);
1325
- vectorLayer.set("_hasActive", true);
1326
- if (vectorLayer.get("_isDynamic")) {
1327
- const activeImage = activeStyle.getImage();
1328
- const previousTimer = vectorLayer.get("_dynamicMarkerTimer");
1329
- if (previousTimer !== void 0) clearTimeout(previousTimer);
1330
- const timer = setTimeout(() => {
1331
- vectorLayer.unset("_dynamicMarkerTimer");
1332
- emitter.emit("dynamic-marker", Object.assign({}, data.rawData || {}, {
1333
- lnglat: data.lnglat,
1334
- style: data.style,
1335
- crsForm: data.crsForm,
1336
- width: activeImage.getWidth(),
1337
- height: activeImage.getHeight()
1338
- }));
1339
- }, 1e3);
1340
- vectorLayer.set("_dynamicMarkerTimer", timer);
1341
- }
1342
- if (vectorLayer.get("_isAutoFit")) {
1343
- const view = instance.getView();
1344
- view.animate({
1345
- duration: 1e3,
1346
- zoom: view.getZoom(),
1347
- center: (0, ol_extent_js.getCenter)(feature.getGeometry().getExtent())
1348
- });
1349
- }
1350
- };
1351
- /**
1352
- * 创建点击交互
1353
- * @param vectorLayer
1354
- */
1355
- const createSelectByLayer = (vectorLayer) => {
1356
- const interaction = new ol_interaction_js.Select({
1357
- style: null,
1358
- multi: false,
1359
- hitTolerance: 10,
1360
- layers: [vectorLayer],
1361
- condition: (evt) => {
1362
- if (!(0, ol_events_condition_js.singleClick)(evt)) return false;
1363
- let hasFeature = false;
1364
- instance.forEachFeatureAtPixel(evt.pixel, () => {
1365
- hasFeature = true;
1366
- }, { layerFilter: (layer) => layer === vectorLayer });
1367
- return hasFeature;
1368
- }
1369
- });
1370
- interaction.on("select", (evt) => {
1371
- const { selected, deselected } = evt;
1372
- if (selected.length) {
1373
- const feature = selected[0];
1374
- if (vectorLayer.get("_isClusterLayer")) {
1375
- const features = feature.get("features");
1376
- if (features.length === 1) selectEventHandle(vectorLayer, features[0]);
1377
- } else selectEventHandle(vectorLayer, feature);
1378
- }
1379
- if (deselected.length) {
1380
- const feature = deselected[0];
1381
- const data = feature.getProperties();
1382
- feature.setStyle(data.unActiveStyle);
1383
- vectorLayer.set("_hasActive", false);
1384
- }
1385
- });
1386
- instance.addInteraction(interaction);
1387
- vectorLayer.set("_selectInteraction", interaction);
1388
- return interaction;
1389
- };
1390
- /** 按多个 className 创建选择交互。 */
1391
- const createLayerSelectByNames = (layerNames, selectedHandler, unSelectHandler) => {
1392
- const interaction = new ol_interaction_js.Select({
1393
- style: null,
1394
- layers: (layer) => layerNames.includes(layer.getClassName())
1395
- });
1396
- interaction.on("select", ({ deselected, selected }) => {
1397
- if (deselected.length) {
1398
- const feature = deselected[0];
1399
- setMarkerSelectedState(feature, false);
1400
- unSelectHandler?.(feature);
1401
- }
1402
- if (selected.length) {
1403
- const feature = selected[0];
1404
- setMarkerSelectedState(feature, true);
1405
- selectedHandler?.(feature);
1406
- }
1407
- });
1408
- return interaction;
1409
- };
1410
-
1411
- //#endregion
1412
- //#region src/interaction/draw.ts
1413
- const formatArea = (polygon) => {
1414
- const area = (0, ol_sphere_js.getArea)(polygon, { projection: "EPSG:4326" });
1415
- return area > 1e4 ? `${Math.round(area / 1e6 * 100) / 100} km\xB2` : `${Math.round(area * 100) / 100} m\xB2`;
1416
- };
1417
- const formatLength = (line) => {
1418
- const length = (0, ol_sphere_js.getLength)(line, { projection: "EPSG:4326" });
1419
- return length > 100 ? `${Math.round(length / 1e3 * 100) / 100} km` : `${Math.round(length * 100) / 100} m`;
1420
- };
1421
- const drawDefaultStyle = new ol_style_js.Style({
1422
- fill: new ol_style_js.Fill({ color: "rgba(255, 255, 255, 0.2)" }),
1423
- stroke: new ol_style_js.Stroke({
1424
- color: "rgba(0, 0, 0, 0.5)",
1425
- lineDash: [10, 10],
1426
- width: 2
1427
- }),
1428
- image: new ol_style_js.Circle({
1429
- radius: 5,
1430
- stroke: new ol_style_js.Stroke({ color: "rgba(0, 0, 0, 0.7)" }),
1431
- fill: new ol_style_js.Fill({ color: "rgba(255, 255, 255, 0.2)" })
1432
- })
1433
- });
1434
- const drawLabelStyleCache = /* @__PURE__ */ new WeakMap();
1435
- const getOrCreateLabelStyle = (feature) => {
1436
- const cached = drawLabelStyleCache.get(feature);
1437
- if (cached) return cached;
1438
- const style = new ol_style_js.Style({
1439
- text: new ol_style_js.Text({
1440
- font: "14px",
1441
- fill: new ol_style_js.Fill({ color: "rgba(255, 255, 255, 1)" }),
1442
- backgroundFill: new ol_style_js.Fill({ color: "rgba(0, 0, 0, 0.7)" }),
1443
- padding: [
1444
- 3,
1445
- 3,
1446
- 3,
1447
- 3
1448
- ],
1449
- textBaseline: "bottom",
1450
- offsetY: -15
1451
- }),
1452
- image: new ol_style_js.RegularShape({
1453
- radius: 8,
1454
- points: 3,
1455
- angle: Math.PI,
1456
- displacement: [0, 10],
1457
- fill: new ol_style_js.Fill({ color: "rgba(0, 0, 0, 0.7)" })
1458
- })
1459
- });
1460
- drawLabelStyleCache.set(feature, style);
1461
- return style;
1462
- };
1463
- /** 为绘制中的线和面追加长度/面积标签。 */
1464
- const getDrawStyle = (feature, drawStyle = drawDefaultStyle) => {
1465
- const styles = drawStyle ? [drawStyle] : [];
1466
- const geometry = feature.getGeometry();
1467
- let point;
1468
- let label;
1469
- if (geometry.getType() === "Polygon") {
1470
- point = geometry.getInteriorPoint();
1471
- label = formatArea(geometry);
1472
- } else if (geometry.getType() === "LineString") {
1473
- point = new ol_geom_Point_js.default(geometry.getLastCoordinate());
1474
- label = formatLength(geometry);
1475
- }
1476
- if (point && label) {
1477
- const labelStyle = getOrCreateLabelStyle(feature);
1478
- labelStyle.setGeometry(point);
1479
- labelStyle.getText().setText(label);
1480
- styles.push(labelStyle);
1481
- }
1482
- return styles;
1483
- };
1484
- /** 创建绘制交互。 */
1485
- const createDrawInteraction = (type = "Point", vectorLayer, openTip) => new ol_interaction_Draw_js.default({
1486
- source: vectorLayer.getSource(),
1487
- type,
1488
- style: openTip ? (feature) => getDrawStyle(feature, void 0) : void 0
1489
- });
1490
-
1491
- //#endregion
1492
- //#region src/layer/geojson-layer.ts
1493
- /** 直接从 GeoJSON 创建矢量图层。 */
1494
- const createGeoJsonLayer = (geoJson, style, config) => {
1495
- const { layerName } = config || {};
1496
- const layerConfig = Object.assign({
1497
- className: layerName || "ol-layer",
1498
- source: new ol_source_Vector_js.default({ features: new ol_format_GeoJSON_js.default().readFeatures(geoJson) }),
1499
- style: style || new ol_style_js.Style({
1500
- stroke: new ol_style_js.Stroke({
1501
- color: "red",
1502
- lineDash: [10],
1503
- width: 3
1504
- }),
1505
- fill: new ol_style_js.Fill({ color: "rgba(0, 0, 255, 0.1)" })
1506
- })
1507
- }, config || {});
1508
- return new ol_layer_Vector_js.default(layerConfig);
1509
- };
1510
-
1511
- //#endregion
1512
- //#region src/layer/vector-layer.ts
1513
- /**
1514
- * 按 colorKey/colorMap 解析颜色,未命中时回退到 fallback
1515
- */
1516
- const resolveColor = (data, colorKey, colorMap, fallback) => colorKey ? colorMap?.get(data[colorKey]) || fallback : fallback;
1517
- /**
1518
- * 组装业务数据为 GeoJson(坐标统一转 WGS84)
1519
- * @param dataList
1520
- * @param config
1521
- */
1522
- const assembleGeoJson = (dataList, config) => {
1523
- const { key, crsForm } = config;
1524
- const tempList = [];
1525
- dataList.forEach((item) => {
1526
- try {
1527
- const raw = item[key];
1528
- const pathArray = Array.isArray(raw) ? raw : JSON.parse(raw || "[]");
1529
- if (pathArray.length) {
1530
- const type = item["geoType"] || determineGeometryType(pathArray);
1531
- if (type !== "Invalid") tempList.push({
1532
- type: "Feature",
1533
- properties: { ...item },
1534
- geometry: {
1535
- type,
1536
- coordinates: pathArray
1537
- }
1538
- });
1539
- }
1540
- } catch (e) {
1541
- console.error(`创建线状数据失败:${e}`);
1542
- }
1543
- });
1544
- return gcoord.default.transform({
1545
- type: "FeatureCollection",
1546
- features: tempList
1547
- }, crsForm || gcoord.default.WGS84, gcoord.default.WGS84);
1548
- };
1549
- const createVectorStyle = (feature, config) => {
1550
- const { isLine, colorMap, fillColor, colorKey, strokeColor, fillOpacity, strokeWeight, activeFillColor, activeFillOpacity, activeStrokeColor, activeStrokeWeight } = config || {};
1551
- const data = feature.getProperties();
1552
- const activeStyle = new ol_style_js.Style({ stroke: new ol_style_js.Stroke({
1553
- width: activeStrokeWeight ?? strokeWeight ?? 4,
1554
- color: activeStrokeColor || resolveColor(data, colorKey, colorMap, strokeColor)
1555
- }) });
1556
- const unActiveStyle = new ol_style_js.Style({ stroke: new ol_style_js.Stroke({
1557
- width: strokeWeight ?? 2,
1558
- color: resolveColor(data, colorKey, colorMap, strokeColor)
1559
- }) });
1560
- if (!isLine) {
1561
- activeStyle.setFill(new ol_style_js.Fill({ color: hexToRgba(activeFillColor || fillColor || "", activeFillOpacity ?? fillOpacity ?? 1) || hexToRgba(resolveColor(data, colorKey, colorMap, fillColor) || "", fillOpacity ?? 1) }));
1562
- unActiveStyle.setFill(new ol_style_js.Fill({ color: hexToRgba(resolveColor(data, colorKey, colorMap, fillColor) || "", fillOpacity ?? 1) }));
1563
- }
1564
- feature.setProperties({
1565
- activeStyle,
1566
- unActiveStyle
1567
- });
1568
- return unActiveStyle;
1569
- };
1570
- const readBusinessFeatures = (dataList, config) => {
1571
- const geoJson = assembleGeoJson(dataList, config);
1572
- const features = new ol_format_js.GeoJSON().readFeatures(geoJson);
1573
- const acceptedData = features.map((feature) => {
1574
- const data = { ...feature.getProperties() };
1575
- delete data.geometry;
1576
- return data;
1577
- });
1578
- features.forEach((feature) => {
1579
- feature.setStyle(createVectorStyle(feature, config));
1580
- });
1581
- return {
1582
- features,
1583
- acceptedData
1584
- };
1585
- };
1586
- /**
1587
- * 创建业务矢量图层(自动推断线/面,生成默认/激活样式)
1588
- * @param dataList
1589
- * @param config
1590
- */
1591
- const createBusinessLayer = (dataList, config) => {
1592
- const { isAutoFit, layerName, openClick } = config;
1593
- const { features, acceptedData } = readBusinessFeatures(dataList, config);
1594
- const vectorLayer = new ol_layer_Vector_js.default({
1595
- zIndex: 5,
1596
- className: layerName ? layerName : "ol-layer",
1597
- source: new ol_source_Vector_js.default({ features })
1598
- });
1599
- if (openClick) createSelectByLayer(vectorLayer);
1600
- vectorLayer.setProperties({
1601
- _isCustom: true,
1602
- _isAutoFit: isAutoFit,
1603
- _isVectorLayer: true,
1604
- _vectorConfig: config,
1605
- _layerName: layerName,
1606
- _dataList: acceptedData,
1607
- _uuidSet: new Set(acceptedData.map((item) => item._uuid))
1608
- });
1609
- return vectorLayer;
1610
- };
1611
- /**
1612
- * 追加 Features
1613
- * @param targetLayer
1614
- * @param dataList
1615
- * @param crsForm
1616
- */
1617
- const appendFeaturesByLayer = (targetLayer, dataList, crsForm) => {
1618
- const vectorSource = targetLayer.getSource();
1619
- const { _vectorConfig: config } = targetLayer.getProperties() || {};
1620
- const { features, acceptedData } = readBusinessFeatures(dataList, Object.assign({}, config, { crsForm }));
1621
- vectorSource.addFeatures(features);
1622
- const uuidSet = new Set(targetLayer.get("_uuidSet") || []);
1623
- acceptedData.forEach((item) => uuidSet.add(item._uuid));
1624
- targetLayer.set("_uuidSet", uuidSet);
1625
- targetLayer.set("_dataList", [...targetLayer.get("_dataList") || [], ...acceptedData]);
1626
- };
1627
- /**
1628
- * 创建面状图层
1629
- * @param dataList
1630
- * @param config
1631
- */
1632
- const createVectorFaceLayer = (dataList = [], config) => createBusinessLayer(dataList, Object.assign({}, config, { isLine: false }));
1633
- /**
1634
- * 创建矢量线图层
1635
- * @param dataList
1636
- * @param config
1637
- */
1638
- const createVectorLineLayer = (dataList = [], config) => createBusinessLayer(dataList, Object.assign({}, config, { isLine: true }));
1639
-
1640
- //#endregion
1641
- //#region src/layer/mass-marks.ts
1642
- /**
1643
- * 构建 MassMarks 样式数组(默认段 + 激活段,长度 statusNum * 2)
1644
- */
1645
- const buildMassMarksStyles = (getImgUrlFn) => {
1646
- return (iconConfig) => {
1647
- const { baseUrl, markerIcon, statusNum = 5, activeScale = 1.3, markerSize = [32, 32] } = iconConfig;
1648
- const getMarkerUrl = getImgUrlFn(baseUrl);
1649
- const [x, y] = markerSize;
1650
- const massMarksStyles = new Array(statusNum * 2);
1651
- for (let i = 0; i < statusNum; i++) {
1652
- const imageUrl = getMarkerUrl(`${markerIcon}-${i}`, ".webp");
1653
- massMarksStyles[i] = new ol_style_js.Style({
1654
- zIndex: 88 + i,
1655
- image: new ol_style_js.Icon({
1656
- width: x,
1657
- height: y,
1658
- src: imageUrl,
1659
- anchor: [.5, 1]
1660
- })
1661
- });
1662
- const activeImage = getMarkerUrl(`${markerIcon}-${i}-active`, ".webp");
1663
- massMarksStyles[i + statusNum] = new ol_style_js.Style({
1664
- zIndex: 120,
1665
- image: new ol_style_js.Icon({
1666
- width: x * activeScale,
1667
- height: y * activeScale,
1668
- anchor: [.5, 1],
1669
- src: activeImage ? activeImage : imageUrl
1670
- })
1671
- });
1672
- }
1673
- return massMarksStyles;
1674
- };
1675
- };
1676
- const createFeatures = (dataList, styleList = []) => {
1677
- return dataList.map((item) => {
1678
- const { crsForm } = item;
1679
- const coord = gcoord.default.transform([+item.lnglat[0], +item.lnglat[1]], crsForm || gcoord.default.WGS84, gcoord.default.WGS84);
1680
- const feature = new ol.Feature({ geometry: new ol_geom_js.Point(coord) });
1681
- feature.setProperties({
1682
- ...item,
1683
- unActiveStyle: styleList[item.style],
1684
- activeStyle: styleList[item.style + styleList.length / 2]
1685
- });
1686
- feature.setStyle(styleList[item.style]);
1687
- return feature;
1688
- });
1689
- };
1690
- /**
1691
- * 向海量点图层增量添加 Features
1692
- * @param targetLayer
1693
- * @param dataList
1694
- * @param config
1695
- */
1696
- const addFeaturesByLayer = (targetLayer, dataList, config = {}) => {
1697
- const massMarksStyles = targetLayer.get("_massMarksStyles");
1698
- const targetSource = targetLayer?.getSource();
1699
- const { clear } = config;
1700
- const features = createFeatures(dataList, massMarksStyles);
1701
- if (clear) targetSource?.clear();
1702
- targetSource?.addFeatures(features);
1703
- const nextData = [...clear ? [] : targetLayer.get("_dataList") || [], ...dataList];
1704
- targetLayer.set("_dataList", nextData);
1705
- targetLayer.set("_uuidSet", new Set(nextData.map((item) => item._uuid)));
1706
- };
1707
- /**
1708
- * 创建 massMarksLayer
1709
- * @param dataList
1710
- * @param styleList
1711
- */
1712
- const createMassMarksLayer = (dataList, styleList = []) => {
1713
- const vectorLayer = new ol_layer_Vector_js.default({
1714
- zIndex: 2e3,
1715
- source: new ol_source_Vector_js.default({ features: createFeatures(dataList, styleList) })
1716
- });
1717
- vectorLayer.setProperties({
1718
- _isCustom: true,
1719
- _isVectorLayer: true,
1720
- _isMassMarksLayer: true,
1721
- _statusNum: styleList.length / 2,
1722
- _dataList: [...dataList],
1723
- _uuidSet: new Set(dataList.map((item) => item._uuid) || [])
1724
- });
1725
- return vectorLayer;
1726
- };
1727
- /**
1728
- * 添加 massMarksLayer(按需附带线/面图层)
1729
- * @param getImgUrlFn
1730
- */
1731
- const addMassMarksLayer = (getImgUrlFn) => {
1732
- return (dataList = [], iconConfig, openClick = true) => {
1733
- const { offset = [0, 0], baseUrl, hasLine, hasFace, layerName, isDynamic, isAutoFit, statusNum, markerIcon, marksStyles, markerSize, activeScale, vectorConfig } = iconConfig;
1734
- const massMarksStyles = marksStyles ? marksStyles : buildMassMarksStyles(getImgUrlFn)({
1735
- baseUrl,
1736
- markerIcon,
1737
- markerSize,
1738
- statusNum: statusNum || 5,
1739
- activeScale: activeScale || 1.3
1740
- });
1741
- const massMarksLayer = createMassMarksLayer(dataList, massMarksStyles);
1742
- if (openClick) {
1743
- massMarksLayer.setProperties({
1744
- _offset: offset,
1745
- _isAutoFit: isAutoFit
1746
- });
1747
- createSelectByLayer(massMarksLayer);
1748
- }
1749
- if (hasLine) {
1750
- const vectorLayer = createBusinessLayer(dataList, Object.assign({}, {
1751
- key: "line",
1752
- isLine: true,
1753
- openClick: false,
1754
- strokeWeight: 4,
1755
- strokeColor: "rgba(29, 235, 255, 0.8)"
1756
- }, vectorConfig || {}));
1757
- instance.addLayer(vectorLayer);
1758
- }
1759
- if (hasFace) {
1760
- const vectorLayer = createBusinessLayer(dataList, Object.assign({}, {
1761
- isLine: false,
1762
- key: "faceList",
1763
- strokeWeight: 1,
1764
- openClick: false,
1765
- fillColor: "#4247DF",
1766
- strokeStyle: "dashed",
1767
- strokeColor: "#4247DF"
1768
- }, vectorConfig || {}));
1769
- instance.addLayer(vectorLayer);
1770
- }
1771
- massMarksLayer.setProperties({
1772
- _isCustom: true,
1773
- _offset: offset,
1774
- _hasLine: hasLine,
1775
- _hasFace: hasFace,
1776
- className: layerName,
1777
- _layerName: layerName,
1778
- _isVectorLayer: true,
1779
- _isDynamic: isDynamic,
1780
- _massMarksStyles: massMarksStyles
1781
- });
1782
- instance.addLayer(massMarksLayer);
1783
- return massMarksLayer;
1784
- };
1785
- };
1786
- /**
1787
- * 按选中状态列表更新海量点显隐
1788
- * @param checkedStatusList
1789
- */
1790
- const updateMarksLayersByStatus = (checkedStatusList = []) => {
1791
- const hideStyle = new ol_style_js.Style({});
1792
- const checkedStatuses = new Set(checkedStatusList);
1793
- const tempList = [];
1794
- instance.getAllLayers().filter((layer) => layer.get("_isMassMarksLayer")).forEach((layer) => {
1795
- layer.getSource().getFeatures().forEach((feature) => {
1796
- const data = feature.getProperties();
1797
- if (!checkedStatuses.has(data.status)) feature.setStyle(hideStyle);
1798
- else {
1799
- tempList.push(data);
1800
- feature.setStyle(data.unActiveStyle);
1801
- }
1802
- });
1803
- });
1804
- return tempList;
1805
- };
1806
-
1807
- //#endregion
1808
- //#region src/layer/cluster-layer.ts
1809
- /**
1810
- * 创建聚合图层(半径/颜色随聚合数量动态计算)
1811
- * @param dataList
1812
- * @param config
1813
- */
1814
- const createClusterLayer = (dataList, config) => {
1815
- const count = dataList.length;
1816
- const styleCache = {};
1817
- const { distance, minDistance, openClick, buildStyle, singleStyles, computedRadius, layerName = "cluster-layer" } = config;
1818
- const innerComputedRadius = (size) => Math.pow(size / count, 1 / 18);
1819
- styleCache[1] = singleStyles;
1820
- const innerBuildStyle = (feature) => {
1821
- const size = feature.get("features").length;
1822
- let style = styleCache[size];
1823
- const tempRadius = computedRadius ? computedRadius(size) : innerComputedRadius(size);
1824
- if (!style) {
1825
- style = new ol_style_js.Style({
1826
- image: new ol_style_Circle_js.default({
1827
- radius: tempRadius * 20,
1828
- stroke: new ol_style_js.Stroke({
1829
- width: 2,
1830
- color: `hsla(${180 - tempRadius * 180}, 100%, 40%, 1)`
1831
- }),
1832
- fill: new ol_style_js.Fill({ color: `hsla(${180 - tempRadius * 180}, 100%, 50%, 1)` })
1833
- }),
1834
- text: new ol_style_js.Text({
1835
- text: size.toString(),
1836
- fill: new ol_style_js.Fill({ color: `hsla(${180 - tempRadius * 180}, 100%, 10%, 1)` }),
1837
- textBaseline: "middle"
1838
- })
1839
- });
1840
- styleCache[size] = style;
1841
- }
1842
- if (Array.isArray(style)) {
1843
- const index = feature.get("features")[0].get("styleIndex") ?? 0;
1844
- return style[index];
1845
- }
1846
- return style;
1847
- };
1848
- const vectorLayer = new ol_layer_Vector_js.default({
1849
- zIndex: 200,
1850
- className: layerName,
1851
- source: new ol_source_Cluster_js.default({
1852
- distance: distance || 80,
1853
- minDistance: minDistance || 0,
1854
- source: new ol_source_Vector_js.default({ features: dataList.map((item) => {
1855
- const feature = new ol.Feature(new ol_geom_js.Point(item.lnglat));
1856
- feature.setProperties(item);
1857
- const index = item.style ?? 0;
1858
- feature.setProperties({
1859
- unActiveStyle: singleStyles[index],
1860
- activeStyle: singleStyles[index + singleStyles.length / 2]
1861
- });
1862
- return feature;
1863
- }) })
1864
- }),
1865
- style: (feature) => buildStyle ? buildStyle(feature) : innerBuildStyle(feature)
1866
- });
1867
- vectorLayer.setProperties({
1868
- _isCustom: true,
1869
- _isVectorLayer: true,
1870
- _isClusterLayer: true
1871
- });
1872
- if (openClick) createSelectByLayer(vectorLayer);
1873
- return vectorLayer;
1874
- };
1875
-
1876
- //#endregion
1877
- exports.GeometryType = GeometryType;
1878
- exports.TDT_VECTOR_SOURCE_ID = TDT_VECTOR_SOURCE_ID;
1879
- exports.TDT_XOR_BYTE_INDEXES = require_tile_loader.TDT_XOR_BYTE_INDEXES;
1880
- exports.TdtDecoderWorkerClient = TdtDecoderWorkerClient;
1881
- exports.activeFeatureByUid = activeFeatureByUid;
1882
- exports.addFeaturesByLayer = addFeaturesByLayer;
1883
- exports.addMassMarksLayer = addMassMarksLayer;
1884
- exports.appendFeaturesByLayer = appendFeaturesByLayer;
1885
- exports.baseLayers = baseLayers;
1886
- exports.buildMassMarksStyles = buildMassMarksStyles;
1887
- exports.changeLayer = changeLayer;
1888
- exports.changeSource = changeSource;
1889
- exports.changeUnselectStyle = changeUnselectStyle;
1890
- exports.createAnimationMarker = createAnimationMarker;
1891
- exports.createBaseLayer = createBaseLayer;
1892
- exports.createBusinessLayer = createBusinessLayer;
1893
- exports.createClusterLayer = createClusterLayer;
1894
- exports.createDrawInteraction = createDrawInteraction;
1895
- exports.createElasticMarkerLayer = createElasticMarkerLayer;
1896
- exports.createGeoJsonLayer = createGeoJsonLayer;
1897
- exports.createIconStyle = createIconStyle;
1898
- exports.createLayerSelectByNames = createLayerSelectByNames;
1899
- exports.createMap = createMap;
1900
- exports.createMapInstance = createMapInstance;
1901
- exports.createMapWorldLayer = createMapWorldLayer;
1902
- exports.createMarker = createMarker;
1903
- exports.createMarkersLayer = createMarkersLayer;
1904
- exports.createMassMarksLayer = createMassMarksLayer;
1905
- exports.createMoveMarkerLayer = createMoveMarkerLayer;
1906
- exports.createOverlay = createOverlay;
1907
- exports.createSelectByLayer = createSelectByLayer;
1908
- exports.createTdtVectorSource = createTdtVectorSource;
1909
- exports.createTdtVtsUrl = createTdtVtsUrl;
1910
- exports.createText = createText;
1911
- exports.createVectorFaceLayer = createVectorFaceLayer;
1912
- exports.createVectorLineLayer = createVectorLineLayer;
1913
- exports.createWmtsLayer = createWmtsLayer;
1914
- exports.createZheJiangLayer = createZheJiangLayer;
1915
- exports.decodeMvt = require_tile_loader.decodeMvt;
1916
- exports.decodeTdtPk = decodeTdtPk;
1917
- exports.disposeInstance = disposeInstance;
1918
- exports.disposeMap = disposeMap;
1919
- exports.emitter = emitter;
1920
- exports.encodeStandardMvt = require_tile_loader.encodeStandardMvt;
1921
- exports.encodeTdtPk = encodeTdtPk;
1922
- exports.flyToAnimate = flyToAnimate;
1923
- exports.getConstantBackgroundColor = getConstantBackgroundColor;
1924
- exports.getDrawStyle = getDrawStyle;
1925
- exports.getLayerByName = getLayerByName;
1926
- exports.getLayersDataList = getLayersDataList;
1927
- exports.getMapInstance = getMapInstance;
1928
- Object.defineProperty(exports, 'instance', {
1929
- enumerable: true,
1930
- get: function () {
1931
- return instance;
1932
- }
1933
- });
1934
- exports.loadAndNormalizeTdtVts = require_tile_loader.loadAndNormalizeTdtVts;
1935
- exports.loadTdtStyleBundle = loadTdtStyleBundle;
1936
- exports.mergeTdtStyleLayers = mergeTdtStyleLayers;
1937
- exports.normalizePrivateGeometry = require_tile_loader.normalizePrivateGeometry;
1938
- exports.normalizePrivateMvt = require_tile_loader.normalizePrivateMvt;
1939
- exports.privateTypeToStandard = require_tile_loader.privateTypeToStandard;
1940
- exports.redactTdtToken = redactTdtToken;
1941
- exports.removeAllLayers = removeAllLayers;
1942
- exports.removeLayerByName = removeLayerByName;
1943
- exports.removeOverlays = removeOverlays;
1944
- exports.resetActiveFeature = resetActiveFeature;
1945
- exports.resetActiveVector = resetActiveVector;
1946
- exports.resetMap = resetMap;
1947
- exports.resetZoomAndCenter = resetZoomAndCenter;
1948
- exports.resolveFeatureProperties = require_tile_loader.resolveFeatureProperties;
1949
- exports.restoreTdtBytes = require_tile_loader.restoreTdtBytes;
1950
- exports.setFitViewByCoords = setFitViewByCoords;
1951
- exports.setFitViewByGeom = setFitViewByGeom;
1952
- exports.setFitViewByLayer = setFitViewByLayer;
1953
- exports.updateMarksLayersByStatus = updateMarksLayersByStatus;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("tdt-vts-core"),l=require("ol/format/MVT.js");l=s(l,1);let u=require("ol/layer/VectorTile.js");u=s(u,1);let d=require("ol/TileState.js");d=s(d,1);let f=require("ol/source/VectorTile.js");f=s(f,1);let p=require("mitt");p=s(p,1);let m=require("ol/source.js"),h=require("ol/layer/Tile.js");h=s(h,1);let g=require("ol/format.js"),_=require("ol/source/WMTS.js"),v=require("ol/tilegrid.js"),y=require("ol/layer.js"),b=require("ol/tilegrid/WMTS.js");b=s(b,1);let ee=require("ol/Observable.js"),x=require("ol/layer/Image.js");x=s(x,1);let S=require("ol/source/Raster.js");S=s(S,1);let C=require("ol/Map.js");C=s(C,1);let w=require("ol/View.js");w=s(w,1);let te=require("ol/control.js"),T=require("gcoord");T=s(T,1);let E=require("ol"),D=require("ol/interaction.js"),ne=require("ol/extent.js"),re=require("ol/events/condition.js"),O=require("ol/Feature.js");O=s(O,1);let k=require("ol/geom/Point.js");k=s(k,1);let A=require("ol/layer/Vector.js");A=s(A,1);let j=require("ol/source/Vector.js");j=s(j,1);let M=require("ol/style.js"),N=require("ol/interaction/Draw.js");N=s(N,1);let ie=require("ol/sphere.js"),P=require("ol/format/GeoJSON.js");P=s(P,1);let ae=require("ol/geom.js"),F=require("ol/source/Cluster.js");F=s(F,1);let I=require("ol/style/Circle.js");I=s(I,1);let oe=function(e){return e.LineString=`LineString`,e.MultiLineString=`MultiLineString`,e.Polygon=`Polygon`,e.MultiPolygon=`MultiPolygon`,e.Invalid=`Invalid`,e}({});const se=async e=>{if(typeof e!=`string`)return e;if(!e.trim())throw TypeError(`style 地址不能为空`);let t=await fetch(e);if(!t.ok)throw Error(`加载 style 失败:HTTP ${t.status}`);return await t.json()},ce=e=>{if(!e.hosts?.length||e.hosts.some(e=>!e.trim()))throw TypeError(`hosts 不能为空`);let t=new c.TdtDecoderWorkerClient(e.restoreMode,e.decoderOptions),n=new l.default({layerName:`mvt:layer`}),r=new f.default({projection:`EPSG:3857`,minZoom:e.minZoom??1,maxZoom:e.maxZoom??18,tileSize:512,wrapX:!0,format:n,attributions:`© <a href="https://www.tianditu.gov.cn/" target="_blank" rel="noopener">天地图</a>`,tileUrlFunction(t){if(!t)return;let[n,r,i]=t;if(n!==void 0&&r!==void 0&&i!==void 0)return(0,c.createTdtVtsUrl)([n,r,i],{token:e.token,hosts:e.hosts,maxZoom:e.maxZoom??18,wrapX:!0})},tileLoadFunction(r,i){let a=r;a.setLoader(async(r,o,s)=>{let l=(0,c.redactTdtToken)(i);try{let o=await t.decode(i),c=n.readFeatures(o.buffer,{extent:r,featureProjection:s});a.setFeatures(c),e.diagnostics?.onDecoded?.(o.stats,l)}catch(t){let n=t instanceof Error?t:Error(String(t));e.diagnostics?.onError?.(n,l),console.error(`天地图私有 VTS 加载失败`,l,n),a.setState(d.default.ERROR)}})}}),i=r.dispose.bind(r);return r.dispose=()=>{t.dispose(),i()},{source:r,decoder:t}},le=async e=>{let t=await se(e.style);if(t?.version!==8||!t.sources||!Array.isArray(t.layers))throw TypeError(`style 必须是 Style v8 对象或其 JSON 地址`);let{source:n}=ce({token:e.token,hosts:e.hosts,restoreMode:`auto`}),r=new u.default({declutter:!0,source:n}),i=r.dispose.bind(r);r.dispose=()=>{n.dispose(),i()};try{let{applyBackground:e,applyStyle:n}=await import(`ol-mapbox-style`),i=structuredClone(t);for(let e of i.layers)e.type===`symbol`&&e.layout?.[`text-font`]&&(e.layout[`text-font`]=[`sans-serif`]);return await Promise.all([n(r,i,{projection:`EPSG:4326`,source:`base-tdt-vector-tile`,updateSource:!1}),e(r,i)]),r}catch(e){throw r.dispose(),e}},L=(0,p.default)();let R;const ue=e=>{R=e},de=()=>{R=void 0},z=(e,t)=>{if(e.startsWith(`#`)){let n=e.replace(`#`,``);return n.length===3&&(n=n[0]+n[0]+n[1]+n[1]+n[2]+n[2]),`rgba(${parseInt(n.substring(0,2),16)}, ${parseInt(n.substring(2,4),16)}, ${parseInt(n.substring(4,6),16)}, ${t})`}return e},fe=()=>R?.getAllLayers().map(e=>e.get(`_dataList`)||[]).flat(2)||[],pe=e=>{let t=e=>!Array.isArray(e)||e.length===0?0:1+t(e[0]),n=e=>{if(!Array.isArray(e)||e.length<3)return!1;let t=e[0],n=e[e.length-1];return t[0]===n[0]&&t[1]===n[1]},r=e=>Array.isArray(e)&&e.length>=2&&typeof e[0]==`number`&&typeof e[1]==`number`,i=e=>Array.isArray(e)&&e.length>=2&&e.every(r),a=e=>Array.isArray(e)?(t(e)===2?[e]:e).every(e=>Array.isArray(e)&&e.length>=4&&n(e)&&e.every(r)):!1,o=t(e);try{return o<2||!e||e.length===0?`Invalid`:o===2&&i(e)?n(e)&&e.length>=4?`Polygon`:`LineString`:o===3&&Array.isArray(e)&&e.every(i)?a(e)?`Polygon`:e.every(e=>!n(e))?`MultiLineString`:`Invalid`:o===4&&Array.isArray(e)&&e.every(e=>a(e))?`MultiPolygon`:`Invalid`}catch(e){return console.error(`Error analyzing coordinates:`,e),`Invalid`}},me=new g.WMTSCapabilities,he=new Map,ge=async e=>{let t=he.get(e);if(t)return t;let n=await fetch(e);if(!n.ok)throw Error(`WMTS capabilities 请求失败:${n.status}`);let r=me.read(await n.text());return he.set(e,r),r},_e=e=>async t=>{let{style:n,format:r,version:i,layerName:a,matrixSet:o}=t,[s,c]=a.split(`:`),l=`${e}/${s}/${c}/gwc/service/wmts?request=GetCapabilities`,u=await ge(l),d=(0,_.optionsFromCapabilities)(u,{style:n||``,layer:c,version:i||`1.1.0`,format:r||`image/png`,matrixSet:o||`EPSG:4326`});if(!d)throw Error(`Unable to create TileLayer`);return new h.default({zIndex:3,className:a,source:new m.WMTS(d)})},ve=`c77eddc667c5bed016fded560baf93e7`,B=(e,t)=>{let n=t.get(`_selectInteraction`);n&&(e.removeInteraction(n),n.dispose(),t.unset(`_selectInteraction`));let r=t.get(`_resolutionChangeKey`);r&&((0,ee.unByKey)(r),t.unset(`_resolutionChangeKey`));let i=t.get(`_dynamicMarkerTimer`);i!==void 0&&(clearTimeout(i),t.unset(`_dynamicMarkerTimer`)),t.getSource()?.dispose(),e.removeLayer(t),t.dispose()},V=(e=`hzsyvector_dark`)=>{let t={zIndex:-5,preload:1,minZoom:8,maxZoom:21,source:new m.XYZ({tileGrid:new v.TileGrid({tileSize:256,resolutions:[.00549933137253187,.00274966568626595,.00137483284313297,.000687416421566485,.000343708210783242,.000171854105391621,859270526958104e-19,429635263479052e-19,214817631739526e-19,107408815869763e-19,537044079348816e-20,268522039674407e-20,134261019837204e-20],origin:[118.122911693886,31.2869311022836],extent:[116.43263049006,28.6201742126026,123.705594256347,31.9765041681924]}),projection:`EPSG:4326`,urls:[`https://ywtg.citybrain.hangzhou.gov.cn/${e}/{z}/{y}/{x}`,`https://ywtg.citybrain.hangzhou.gov.cn:9456/${e}/{z}/{y}/{x}`,`https://ywtg.citybrain.hangzhou.gov.cn:9457/${e}/{z}/{y}/{x}`,`https://ywtg.citybrain.hangzhou.gov.cn:9458/${e}/{z}/{y}/{x}`,`https://ywtg.citybrain.hangzhou.gov.cn:9459/${e}/{z}/{y}/{x}`]}),properties:{_isBaseLayer:!0,_layerName:e}};return new y.Tile(t)},ye=(e,t=ve)=>{let[n,r]=e.split(`_`),i={preload:1,zIndex:-10,cacheSize:20240,properties:{_isBaseLayer:!0,_layerName:e},source:new m.WMTS({crossOrigin:`anonymous`,projection:`EPSG:4326`,wrapX:!0,layer:n,style:`default`,version:`1.0.0`,format:`image/png`,matrixSet:r,tileGrid:new b.default({tileSize:256,origin:[-180,90],matrixIds:[`1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`,`10`,`11`,`12`,`13`,`14`,`15`,`16`,`17`,`18`,`19`],resolutions:[.703125,.3515625,.17578125,.087890625,.0439453125,.02197265625,.010986328125,.0054931640625,.00274658203125,.001373291015625,.0006866455078125,.00034332275390625,.000171661376953125,858306884765625e-19,4291534423828125e-20,21457672119140625e-21,10728836059570312e-21,5364418029785156e-21,2682209014892578e-21]}),url:`https://t{0-7}.tianditu.gov.cn/${e}/wmts?tk=${t}`})};return new y.Tile(i)},be=e=>({baseImgLayer:new y.Tile({className:`img-layer`,source:new m.XYZ({crossOrigin:`anonymous`,tileSize:256,url:`https://t{0-7}.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=${e}`}),zIndex:1}),baseCiaLayer:new y.Tile({className:`img-layer`,source:new m.XYZ({crossOrigin:`anonymous`,tileSize:256,url:`https://t{0-7}.tianditu.gov.cn/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=${e}`}),zIndex:2}),baseVecLayer:new y.Tile({className:`vec-layer`,source:new m.XYZ({crossOrigin:`anonymous`,tileSize:256,url:`https://t{0-7}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=${e}`}),zIndex:1}),baseCvaLayer:new y.Tile({className:`vec-layer`,source:new m.XYZ({crossOrigin:`anonymous`,tileSize:256,url:`https://t{0-7}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=${e}`}),zIndex:2})}),xe=(e=`emap`,t=`3b0cdd02-c366-4363-b6de-081a9f12b364`)=>new y.Tile({preload:1,minZoom:4,maxZoom:20,zIndex:-10,cacheSize:20240,source:new m.XYZ({wrapX:!0,projection:`EPSG:4326`,crossOrigin:`anonymous`,url:`https://ditu{0-6}.zjzwfw.gov.cn/services/wmts/${e}/default/oss/getTile/{z}/{y}/{x}?token=${t}`})}),Se=e=>R.getAllLayers().find(t=>(t.get(`_layerName`)||t.getClassName())===e),Ce=e=>{let t=Se(e);t&&B(R,t)},we=()=>Math.max(1,Math.min(4,globalThis.navigator?.hardwareConcurrency??2)),H=(e,t,n,r={})=>{let i=new S.default({sources:[e],operationType:`image`,operation:(e,t)=>(((e,t)=>{let n=t.ratioArray,r=t.rgbColorArray;if(n&&r){let[t=0,i=0,a=0]=n;for(let n=0;n<e.length;n+=4){let o=e[n],s=e[n+1],c=e[n+2],l=o*t+s*i+c*a;e[n]=r[0]-l,e[n+1]=r[1]-l,e[n+2]=r[2]-l}}})(e[0].data,t),e[0]),threads:r.threads??we()});return i.on(`beforeoperations`,e=>{e.data.ratioArray=n,e.data.rgbColorArray=t}),i},Te=(e,t,n,r={})=>new x.default({source:H(e,t,n,r)}),U=(e=``)=>{R&&R.getOverlays().getArray().filter(t=>t.get(e||`position`)).forEach(e=>R.removeOverlay(e))},Ee=()=>U(`_isAnimationMarker`),De=(e,t)=>{Ee();let{width:n,height:r,lnglat:i,crsForm:a}=t,o=document.createElement(`div`),s=document.createElement(`img`);s.src=e,s.alt=``,n!==void 0&&(s.width=n),r!==void 0&&(s.height=r),o.append(s);let c=new E.Overlay({element:o,stopEvent:!1,positioning:`bottom-center`,position:T.default.transform([+i[0],+i[1]],a||T.default.WGS84,T.default.WGS84)});c.set(`_isAnimationMarker`,!0),R.addOverlay(c)},Oe=(e={id:`popup-container`,positioning:`top-center`})=>new E.Overlay(Object.assign({element:document.getElementById(e.id)||void 0},e)),ke=()=>{U(),R.getAllLayers().forEach(e=>{e.get(`_selectInteraction`)?.getFeatures().clear()})},Ae=()=>{U(),R&&R.getAllLayers().forEach(e=>{e.get(`_isBaseLayer`)||B(R,e)})},je=()=>{U(),R.getAllLayers().filter(e=>e.get(`_isVectorLayer`)).forEach(e=>{let t=e.get(`_selectInteraction`);t&&(t.dispatchEvent({type:`select`,selected:[],mapBrowserEvent:void 0,deselected:t.getFeatures().getArray()}),t.getFeatures().clear())})},Me=e=>{let t=R.getAllLayers().filter(e=>e.get(`_isVectorLayer`));if(t.length){let n=t.find(t=>t.get(`_uuidSet`).has(e)&&t.get(`_selectInteraction`));if(n){let t=(n.getSource()?.getFeatures()||[]).find(t=>t.get(`_uuid`)===e),r=n.get(`_selectInteraction`);if(r){let n=r.getFeatures().getArray();n.find(t=>t.get(`_uuid`)===e)||(r.dispatchEvent({type:`select`,deselected:n,selected:[t],mapBrowserEvent:void 0}),r.getFeatures().push(t))}}}};let W=[119.71512016971076,30.122490541963536];const Ne=(e={})=>{if(R)return R;let t=Pe(e);return ue(t),t},Pe=(e={})=>{let t=Object.assign({zoom:9.4,maxZoom:18,minZoom:9.4,center:W,baseLayer:`vec-layer`,projection:`EPSG:4326`,layers:[V()],constrainResolution:!1,smoothExtentConstraint:!1,tk:ve},e||{}),n=new C.default({view:new w.default(t),controls:(0,te.defaults)({zoom:!1,rotate:!1,attribution:!1}),interactions:(0,D.defaults)({pinchRotate:!1,doubleClickZoom:!1,altShiftDragRotate:!1}),layers:t.layers||[V()]});W=t.center||W,n.activeBaseLayer=t.baseLayer;let r=e=>n.getAllLayers().find(t=>(t.get(`_layerName`)||t.getClassName())===e);n.getLayerByName=r,n.removeLayerByName=e=>{let t=r(e);t&&B(n,t)},n.changeLayersByNames=(e,t)=>{n.getAllLayers().filter(e=>t.includes(e.getClassName())).forEach(t=>t.setVisible(e?.includes(t.getClassName())))};let i,a;return n.on(`pointermove`,e=>{if(a=e.pixel,i!==void 0)return;let t=()=>{i=void 0,a&&(n.getTargetElement().style.cursor=n.hasFeatureAtPixel(a)?`pointer`:``)};i=typeof globalThis.requestAnimationFrame==`function`?globalThis.requestAnimationFrame(t):setTimeout(t,16)}),n.set(`_disposePointerMove`,()=>{i!==void 0&&(typeof globalThis.cancelAnimationFrame==`function`?globalThis.cancelAnimationFrame(i):clearTimeout(i),i=void 0)}),n},Fe=()=>{if(!R)return;let e=R;e.get(`_disposePointerMove`)?.(),e.unset(`_disposePointerMove`),e.getOverlays().forEach(t=>{e.removeOverlay(t)}),e.getInteractions().clear(),e.getAllLayers().forEach(t=>B(e,t)),e.setTarget(``),e.dispose(),de()},Ie=()=>Fe(),Le=()=>R,Re=(e=W)=>{R&&R.getView().animate({zoom:9.4,center:e,duration:1e3})},ze=(e={center:W,isClearAll:!0})=>{Ae(),Re(e.center||W)},G={padding:[50,50,50,50],duration:1e3},Be=(e,t=R,n)=>{let r=t.getView();if(e.length===1)r.animate({zoom:14,duration:1e3,center:e[0],...n||{}});else{let t=(0,ne.boundingExtent)(e);r.fit(t,{...G,...n||{}})}},Ve=(e,t=R,n)=>{t.getView().fit(e,{...G,...n||{}})},He=(e,t=R,n)=>{let r=e.getSource();if(!r||r.isEmpty())return;let i=r.getExtent();i&&t.getView().fit(i,{...G,...n||{}})},Ue=(e,t)=>{let n=R.getView(),r=n.getZoom();n.animate({center:e,duration:2e3}),t?n.animate({zoom:t-2,duration:1e3},{zoom:t,duration:1e3}):n.animate({zoom:r-2,duration:1e3},{zoom:r+2>12?12:r+2,duration:1e3})},We=e=>new M.Text({text:e.text,offsetY:e.offsetY,offsetX:e.offsetX,justify:`center`,textAlign:`center`,font:`16px PingFangSC-Semibold`,fill:new M.Fill({color:`rgba(255, 255, 255, 0.8)`})}),K=(e,t=!1)=>new M.Style({image:new M.Icon({scale:e.scale||1,rotation:e.rotation||0,anchor:e.anchor||[.5,1],src:t&&e.activeImg||e.img}),text:e.showText?We(e):void 0}),q=(e,t)=>{let n=new O.default({geometry:new k.default([+e.lng,+e.lat]),data:Object.assign({},e||{},{layerName:t.layerName})});return n.setStyle(K(e)),n},Ge=(e,t)=>{let{layerName:n,visible:r=!0,zIndex:i=10}=t,a=new j.default;return e.forEach(e=>a.addFeature(q(e,t))),new A.default({zIndex:i,visible:r,source:a,className:n||`marker-layer`})},J=(e,t)=>{let n=t>=14?`largeImg`:t>=11?`smallImg`:`img`;e.forEach(e=>{let t=e.get(`data`);t.isSelected||e.setStyle(K({...t,img:t[n]},!1))})},Y=(e,t)=>{let n=e.get(`data`),r={...n,isSelected:t};e.set(`data`,r),n.isElastic?J([e],R.getView().getZoom()):e.setStyle(K(r,t))},Ke=e=>{e.forEach(e=>{Y(e,!1)}),e.clear()},qe=(e,t)=>{let n=e.map(e=>({...e,isElastic:!0})),r=Ge(n,t),i=r.getSource().getFeatures(),a=R.getView();return J(i,a.getZoom()),r.set(`_resolutionChangeKey`,a.on(`change:resolution`,()=>J(i,a.getZoom()))),r},Je=(e,t)=>{let n=q(e,t),r=new A.default({className:t.layerName||`ol-layer`,source:new j.default({features:[n]})});return R.addLayer(r),{vectorLayer:r}},Ye=(e,t)=>{let n=t.getProperties(),{activeStyle:r}=n;if(t.setStyle(r),L.emit(`selected-feature`,n),e.set(`_hasActive`,!0),e.get(`_isDynamic`)){let t=r.getImage(),i=e.get(`_dynamicMarkerTimer`);i!==void 0&&clearTimeout(i);let a=setTimeout(()=>{e.unset(`_dynamicMarkerTimer`),L.emit(`dynamic-marker`,Object.assign({},n.rawData||{},{lnglat:n.lnglat,style:n.style,crsForm:n.crsForm,width:t.getWidth(),height:t.getHeight()}))},1e3);e.set(`_dynamicMarkerTimer`,a)}if(e.get(`_isAutoFit`)){let e=R.getView();e.animate({duration:1e3,zoom:e.getZoom(),center:(0,ne.getCenter)(t.getGeometry().getExtent())})}},X=e=>{let t=new D.Select({style:null,multi:!1,hitTolerance:10,layers:[e],condition:t=>{if(!(0,re.singleClick)(t))return!1;let n=!1;return R.forEachFeatureAtPixel(t.pixel,()=>{n=!0},{layerFilter:t=>t===e}),n}});return t.on(`select`,t=>{let{selected:n,deselected:r}=t;if(n.length){let t=n[0];if(e.get(`_isClusterLayer`)){let n=t.get(`features`);n.length===1&&Ye(e,n[0])}else Ye(e,t)}if(r.length){let t=r[0],n=t.getProperties();t.setStyle(n.unActiveStyle),e.set(`_hasActive`,!1)}}),R.addInteraction(t),e.set(`_selectInteraction`,t),t},Xe=(e,t,n)=>{let r=new D.Select({style:null,layers:t=>e.includes(t.getClassName())});return r.on(`select`,({deselected:e,selected:r})=>{if(e.length){let t=e[0];Y(t,!1),n?.(t)}if(r.length){let e=r[0];Y(e,!0),t?.(e)}}),r},Ze=e=>{let t=(0,ie.getArea)(e,{projection:`EPSG:4326`});return t>1e4?`${Math.round(t/1e6*100)/100} km\xB2`:`${Math.round(t*100)/100} m\xB2`},Qe=e=>{let t=(0,ie.getLength)(e,{projection:`EPSG:4326`});return t>100?`${Math.round(t/1e3*100)/100} km`:`${Math.round(t*100)/100} m`},$e=new M.Style({fill:new M.Fill({color:`rgba(255, 255, 255, 0.2)`}),stroke:new M.Stroke({color:`rgba(0, 0, 0, 0.5)`,lineDash:[10,10],width:2}),image:new M.Circle({radius:5,stroke:new M.Stroke({color:`rgba(0, 0, 0, 0.7)`}),fill:new M.Fill({color:`rgba(255, 255, 255, 0.2)`})})}),et=new WeakMap,tt=e=>{let t=et.get(e);if(t)return t;let n=new M.Style({text:new M.Text({font:`14px`,fill:new M.Fill({color:`rgba(255, 255, 255, 1)`}),backgroundFill:new M.Fill({color:`rgba(0, 0, 0, 0.7)`}),padding:[3,3,3,3],textBaseline:`bottom`,offsetY:-15}),image:new M.RegularShape({radius:8,points:3,angle:Math.PI,displacement:[0,10],fill:new M.Fill({color:`rgba(0, 0, 0, 0.7)`})})});return et.set(e,n),n},nt=(e,t=$e)=>{let n=t?[t]:[],r=e.getGeometry(),i,a;if(r.getType()===`Polygon`?(i=r.getInteriorPoint(),a=Ze(r)):r.getType()===`LineString`&&(i=new k.default(r.getLastCoordinate()),a=Qe(r)),i&&a){let t=tt(e);t.setGeometry(i),t.getText().setText(a),n.push(t)}return n},rt=(e=`Point`,t,n)=>new N.default({source:t.getSource(),type:e,style:n?e=>nt(e,void 0):void 0}),it=(e,t,n)=>{let{layerName:r}=n||{},i=Object.assign({className:r||`ol-layer`,source:new j.default({features:new P.default().readFeatures(e)}),style:t||new M.Style({stroke:new M.Stroke({color:`red`,lineDash:[10],width:3}),fill:new M.Fill({color:`rgba(0, 0, 255, 0.1)`})})},n||{});return new A.default(i)},Z=(e,t,n,r)=>t&&n?.get(e[t])||r,at=(e,t)=>{let{key:n,crsForm:r}=t,i=[];return e.forEach(e=>{try{let t=e[n],r=Array.isArray(t)?t:JSON.parse(t||`[]`);if(r.length){let t=e.geoType||pe(r);t!==`Invalid`&&i.push({type:`Feature`,properties:{...e},geometry:{type:t,coordinates:r}})}}catch(e){console.error(`创建线状数据失败:${e}`)}}),T.default.transform({type:`FeatureCollection`,features:i},r||T.default.WGS84,T.default.WGS84)},ot=(e,t)=>{let{isLine:n,colorMap:r,fillColor:i,colorKey:a,strokeColor:o,fillOpacity:s,strokeWeight:c,activeFillColor:l,activeFillOpacity:u,activeStrokeColor:d,activeStrokeWeight:f}=t||{},p=e.getProperties(),m=new M.Style({stroke:new M.Stroke({width:f??c??4,color:d||Z(p,a,r,o)})}),h=new M.Style({stroke:new M.Stroke({width:c??2,color:Z(p,a,r,o)})});return n||(m.setFill(new M.Fill({color:z(l||i||``,u??s??1)||z(Z(p,a,r,i)||``,s??1)})),h.setFill(new M.Fill({color:z(Z(p,a,r,i)||``,s??1)}))),e.setProperties({activeStyle:m,unActiveStyle:h}),h},st=(e,t)=>{let n=at(e,t),r=new g.GeoJSON().readFeatures(n),i=r.map(e=>{let t={...e.getProperties()};return delete t.geometry,t});return r.forEach(e=>{e.setStyle(ot(e,t))}),{features:r,acceptedData:i}},Q=(e,t)=>{let{isAutoFit:n,layerName:r,openClick:i}=t,{features:a,acceptedData:o}=st(e,t),s=new A.default({zIndex:5,className:r||`ol-layer`,source:new j.default({features:a})});return i&&X(s),s.setProperties({_isCustom:!0,_isAutoFit:n,_isVectorLayer:!0,_vectorConfig:t,_layerName:r,_dataList:o,_uuidSet:new Set(o.map(e=>e._uuid))}),s},ct=(e,t,n)=>{let r=e.getSource(),{_vectorConfig:i}=e.getProperties()||{},{features:a,acceptedData:o}=st(t,Object.assign({},i,{crsForm:n??i?.crsForm}));r.addFeatures(a);let s=new Set(e.get(`_uuidSet`)||[]);o.forEach(e=>s.add(e._uuid)),e.set(`_uuidSet`,s),e.set(`_dataList`,[...e.get(`_dataList`)||[],...o])},lt=(e=[],t)=>Q(e,Object.assign({},t,{isLine:!1})),ut=(e=[],t)=>Q(e,Object.assign({},t,{isLine:!0})),dt=e=>t=>{let{baseUrl:n,markerIcon:r,statusNum:i=5,activeScale:a=1.3,markerSize:o=[32,32]}=t,s=e(n),[c,l]=o,u=Array(i*2);for(let e=0;e<i;e++){let t=s(`${r}-${e}`,`.webp`);u[e]=new M.Style({zIndex:88+e,image:new M.Icon({width:c,height:l,src:t,anchor:[.5,1]})});let n=s(`${r}-${e}-active`,`.webp`);u[e+i]=new M.Style({zIndex:120,image:new M.Icon({width:c*a,height:l*a,anchor:[.5,1],src:n||t})})}return u},ft=(e,t=[])=>e.map(e=>{let{crsForm:n}=e,r=T.default.transform([+e.lnglat[0],+e.lnglat[1]],n||T.default.WGS84,T.default.WGS84),i=new E.Feature({geometry:new ae.Point(r)});return i.setProperties({...e,unActiveStyle:t[e.style],activeStyle:t[e.style+t.length/2]}),i.setStyle(t[e.style]),i}),pt=(e,t,n={})=>{let r=e.get(`_massMarksStyles`),i=e?.getSource(),{clear:a}=n,o=ft(t,r);a&&i?.clear(),i?.addFeatures(o);let s=[...a?[]:e.get(`_dataList`)||[],...t];e.set(`_dataList`,s),e.set(`_uuidSet`,new Set(s.map(e=>e._uuid)))},$=(e,t=[])=>{let n=new A.default({zIndex:2e3,source:new j.default({features:ft(e,t)})});return n.setProperties({_isCustom:!0,_isVectorLayer:!0,_isMassMarksLayer:!0,_statusNum:t.length/2,_dataList:[...e],_uuidSet:new Set(e.map(e=>e._uuid)||[])}),n},mt=e=>(t=[],n,r=!0)=>{let{offset:i=[0,0],baseUrl:a,hasLine:o,hasFace:s,layerName:c,isDynamic:l,isAutoFit:u,statusNum:d,markerIcon:f,marksStyles:p,markerSize:m,activeScale:h,vectorConfig:g}=n,_=p||dt(e)({baseUrl:a,markerIcon:f,markerSize:m,statusNum:d||5,activeScale:h||1.3}),v=$(t,_);if(r&&(v.setProperties({_offset:i,_isAutoFit:u}),X(v)),o){let e=Q(t,Object.assign({},{key:`line`,isLine:!0,openClick:!1,strokeWeight:4,strokeColor:`rgba(29, 235, 255, 0.8)`},g||{}));R.addLayer(e)}if(s){let e=Q(t,Object.assign({},{isLine:!1,key:`faceList`,strokeWeight:1,openClick:!1,fillColor:`#4247DF`,strokeStyle:`dashed`,strokeColor:`#4247DF`},g||{}));R.addLayer(e)}return v.setProperties({_isCustom:!0,_offset:i,_hasLine:o,_hasFace:s,className:c,_layerName:c,_isVectorLayer:!0,_isDynamic:l,_massMarksStyles:_}),R.addLayer(v),v},ht=(e=[])=>{let t=new M.Style({}),n=new Set(e),r=[];return R.getAllLayers().filter(e=>e.get(`_isMassMarksLayer`)).forEach(e=>{e.getSource().getFeatures().forEach(e=>{let i=e.getProperties();n.has(i.status)?(r.push(i),e.setStyle(i.unActiveStyle)):e.setStyle(t)})}),r},gt=(e,t)=>{let n=e.length,r={},{distance:i,minDistance:a,openClick:o,buildStyle:s,singleStyles:c,computedRadius:l,layerName:u=`cluster-layer`}=t,d=e=>(e/n)**(1/18);r[1]=c;let f=e=>{let t=e.get(`features`).length,n=r[t],i=l?l(t):d(t);if(n||(n=new M.Style({image:new I.default({radius:i*20,stroke:new M.Stroke({width:2,color:`hsla(${180-i*180}, 100%, 40%, 1)`}),fill:new M.Fill({color:`hsla(${180-i*180}, 100%, 50%, 1)`})}),text:new M.Text({text:t.toString(),fill:new M.Fill({color:`hsla(${180-i*180}, 100%, 10%, 1)`}),textBaseline:`middle`})}),r[t]=n),Array.isArray(n)){let t=e.get(`features`)[0].get(`styleIndex`)??0;return n[t]}return n},p=new A.default({zIndex:200,className:u,source:new F.default({distance:i||80,minDistance:a||0,source:new j.default({features:e.map(e=>{let t=new E.Feature(new ae.Point(e.lnglat));t.setProperties(e);let n=e.style??0;return t.setProperties({unActiveStyle:c[n],activeStyle:c[n+c.length/2]}),t})})}),style:e=>s?s(e):f(e)});return p.setProperties({_isCustom:!0,_isVectorLayer:!0,_isClusterLayer:!0}),o&&X(p),p};exports.GeometryType=oe,exports.activeFeatureByUid=Me,exports.addFeaturesByLayer=pt,exports.addMassMarksLayer=mt,exports.appendFeaturesByLayer=ct,exports.baseLayers=be,exports.buildMassMarksStyles=dt,exports.changeLayer=Te,exports.changeSource=H,exports.changeUnselectStyle=Ke,exports.createAnimationMarker=De,exports.createBaseLayer=V,exports.createBusinessLayer=Q,exports.createClusterLayer=gt,exports.createDrawInteraction=rt,exports.createElasticMarkerLayer=qe,exports.createGeoJsonLayer=it,exports.createIconStyle=K,exports.createLayerSelectByNames=Xe,exports.createMap=Pe,exports.createMapInstance=Ne,exports.createMapWorldLayer=ye,exports.createMarker=q,exports.createMarkersLayer=Ge,exports.createMassMarksLayer=$,exports.createMoveMarkerLayer=Je,exports.createOverlay=Oe,exports.createSelectByLayer=X,exports.createTdtVectorSource=ce,exports.createTdtVtsLayer=le,exports.createText=We,exports.createVectorFaceLayer=lt,exports.createVectorLineLayer=ut,exports.createWmtsLayer=_e,exports.createZheJiangLayer=xe,exports.disposeInstance=Ie,exports.disposeMap=Fe,exports.emitter=L,exports.flyToAnimate=Ue,exports.getDrawStyle=nt,exports.getLayerByName=Se,exports.getLayersDataList=fe,exports.getMapInstance=Le,Object.defineProperty(exports,"instance",{enumerable:!0,get:function(){return R}}),exports.removeAllLayers=Ae,exports.removeLayerByName=Ce,exports.removeOverlays=U,exports.resetActiveFeature=je,exports.resetActiveVector=ke,exports.resetMap=ze,exports.resetZoomAndCenter=Re,exports.setFitViewByCoords=Be,exports.setFitViewByGeom=Ve,exports.setFitViewByLayer=He,exports.updateMarksLayersByStatus=ht,Object.keys(c).forEach(function(e){e!=="default"&&!Object.prototype.hasOwnProperty.call(exports,e)&&Object.defineProperty(exports,e,{enumerable:!0,get:function(){return c[e]}})});