@3clear/basegis 0.1.0 → 0.1.1
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/README.md +2023 -344
- package/dist/basegis.js +3244 -1382
- package/dist/methods.js +547 -483
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# @3clear/basegis
|
|
2
2
|
|
|
3
3
|
`@3clear/basegis` 是 3clear 一张图项目抽出的 GIS 能力包。它提供一个统一入口 `BaseGIS`,把 Cesium / Leaflet 的差异收敛到适配层里;业务页面优先只操作 `BaseGIS`,复杂图层能力通过 `methods` 控制器组合 `BaseGIS` 公共方法完成。
|
|
4
|
-
|
|
4
|
+
把leaflet cesium 常用方法做了二次封装统一了api 使同一套代码可以适配2套地图引擎
|
|
5
5
|
当前包包含:
|
|
6
6
|
|
|
7
|
-
- `BaseGIS`:地图初始化、引擎切换、视角控制、底图切换、绘制、图层显隐、DEM
|
|
7
|
+
- `BaseGIS`:地图初始化、引擎切换、视角控制、底图切换、绘制、图层显隐、DEM、点击事件、三维体渲染、三维切片/剖面渲染等基础能力。
|
|
8
8
|
- `methods`:图片图层、网格图层、海量点、点位抽稀、等值线、等压线、风场、图形组等高级控制器。
|
|
9
9
|
- `layers`:天地图、GeoServer 金字塔瓦片、WMS、WMTS 图层配置快捷构造器。
|
|
10
10
|
- `assets`:GIS 示例资源。
|
|
@@ -22,8 +22,7 @@ npm install @3clear/basegis leaflet axios pixi.js leaflet-pixi-overlay
|
|
|
22
22
|
import '@3clear/basegis/style.css'
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
Cesium 当前不随 npm 包发布,宿主项目需要按原项目方式把 Cesium 静态资源放到 `public/lib/Cesium`,并保证初始化前能访问 `window.Cesium
|
|
26
|
-
|
|
25
|
+
Cesium 当前不随 npm 包发布,宿主项目需要按原项目方式把 Cesium 静态资源放到 `public/lib/Cesium`,并保证初始化前能访问 `window.Cesium`。
|
|
27
26
|
如果需要加载 GeoTIFF 网格,需要宿主项目提前提供 `window.GeoTIFF`。
|
|
28
27
|
|
|
29
28
|
## 出口
|
|
@@ -91,6 +90,12 @@ onMounted(() => {
|
|
|
91
90
|
pitch: -90,
|
|
92
91
|
},
|
|
93
92
|
},
|
|
93
|
+
basemap: {
|
|
94
|
+
// 默认内置值:tianditu-imagery。
|
|
95
|
+
defaultVisibleId: 'tianditu-imagery',
|
|
96
|
+
// 默认内置值:tianditu-vector-label。
|
|
97
|
+
defaultAnnotationId: 'tianditu-vector-label',
|
|
98
|
+
},
|
|
94
99
|
},
|
|
95
100
|
})
|
|
96
101
|
|
|
@@ -133,263 +138,526 @@ onBeforeUnmount(() => {
|
|
|
133
138
|
message: 'error message',
|
|
134
139
|
code: 'NOT_INITIALIZED'
|
|
135
140
|
}
|
|
141
|
+
|
|
136
142
|
```
|
|
137
143
|
|
|
138
|
-
|
|
144
|
+
说明:
|
|
145
|
+
|
|
146
|
+
- `containerId` 和 `container` 二选一即可;`init()` 时也可以再次传入。
|
|
147
|
+
- 页面传入的 `config` 会覆盖内置默认配置。
|
|
148
|
+
- `basemap.list` 和 `dem.list` 是数组,外部传入时会整体覆盖内置列表;如果要使用内置默认底图,不要传空数组覆盖。
|
|
149
|
+
- Cesium 默认视角 `pitch: -90`,表示垂直俯视。
|
|
150
|
+
- `BaseGIS` 只保存运行时配置,调用 `setConfig()` 不会自动重建地图,需要重新 `init()` 才会创建新地图实例。
|
|
151
|
+
|
|
152
|
+
### 默认底图配置
|
|
139
153
|
|
|
140
|
-
|
|
154
|
+
不传 `config.basemap` 时,内置默认配置如下:
|
|
141
155
|
|
|
142
156
|
```js
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
157
|
+
basemap: {
|
|
158
|
+
defaultVisibleId: 'tianditu-imagery',
|
|
159
|
+
defaultAnnotationId: 'tianditu-vector-label',
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
默认底图列表:
|
|
164
|
+
|
|
165
|
+
| id | 名称 | category | enabled | type | provider | resourceKey | 默认用途 | 引擎支持 |
|
|
166
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
167
|
+
| `tianditu-vector` | 天地图矢量底图 | `basemap` | `true` | `wmts` | `tianditu` | `vector` | 可作为 `defaultVisibleId` | Cesium / Leaflet |
|
|
168
|
+
| `tianditu-imagery` | 天地图影像底图 | `basemap` | `true` | `wmts` | `tianditu` | `imagery` | 内置 `defaultVisibleId` | Cesium / Leaflet |
|
|
169
|
+
| `tianditu-terrain` | 天地图地形底图 | `basemap` | `true` | `wmts` | `tianditu` | `terrain` | 可作为 `defaultVisibleId` | Cesium / Leaflet |
|
|
170
|
+
| `tianditu-vector-label` | 天地图矢量注记 | `annotation` | `true` | `wmts` | `tianditu` | `vectorLabel` | 内置 `defaultAnnotationId` | Cesium / Leaflet |
|
|
171
|
+
| `tianditu-terrain-label` | 天地图地形注记 | `annotation` | `true` | `wmts` | `tianditu` | `terrainLabel` | 可作为 `defaultAnnotationId` | Cesium / Leaflet |
|
|
172
|
+
|
|
173
|
+
可用于 `defaultVisibleId` 的内置底图 id:
|
|
174
|
+
|
|
175
|
+
- `tianditu-vector`
|
|
176
|
+
- `tianditu-imagery`
|
|
177
|
+
- `tianditu-terrain`
|
|
178
|
+
|
|
179
|
+
可用于 `defaultAnnotationId` 的内置注记 id:
|
|
180
|
+
|
|
181
|
+
- `tianditu-vector-label`
|
|
182
|
+
- `tianditu-terrain-label`
|
|
183
|
+
|
|
184
|
+
说明:
|
|
185
|
+
|
|
186
|
+
- `defaultVisibleId` 应指向 `category: 'basemap'` 的底图。
|
|
187
|
+
- `defaultAnnotationId` 应指向 `category: 'annotation'` 的注记层。
|
|
188
|
+
- `tianditu-terrain` 是天地图地形底图瓦片,不是 Cesium 的 DEM 高程地形;如果要控制 Cesium terrainProvider,请看后文 DEM。
|
|
189
|
+
- `geoserver-wmts-sample` 和 `geoserver-wms-sample` 默认 `enabled: false`,只是配置格式示例;如果要作为默认底图,需要替换真实服务地址并改为 `enabled: true`。
|
|
190
|
+
- 天地图 provider 内置资源还包括 `imageryLabel`;默认 `basemap.list` 没有单独注册影像注记 id,但 `resourceKey: 'imagery'` 会自动推断使用 `imageryLabel` 注记。
|
|
191
|
+
|
|
192
|
+
### 底图切换
|
|
193
|
+
|
|
194
|
+
底图可以来自 `config.basemap.list`,也可以直接传配置对象。当前适配层支持:
|
|
195
|
+
|
|
196
|
+
- 天地图:`provider: 'tianditu'` 或传 `resourceKey`
|
|
197
|
+
- URL 模板瓦片:`type: 'wmts' / 'xyz' / 'tile'`
|
|
198
|
+
- WMS:`type: 'wms'`
|
|
199
|
+
|
|
200
|
+
按配置 id 切换:
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
const result = mapCore.setBasemapById('tianditu-imagery')
|
|
204
|
+
if (!result.success) {
|
|
205
|
+
console.warn(result.message)
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
直接传底图配置:
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
|
|
213
|
+
mapCore.setBasemap({
|
|
214
|
+
id: 'custom-xyz',
|
|
215
|
+
name: '自定义 XYZ',
|
|
216
|
+
category: 'basemap',
|
|
217
|
+
type: 'xyz',
|
|
218
|
+
provider: 'custom',
|
|
219
|
+
url: 'https://example.com/tiles/{z}/{x}/{y}.png',
|
|
220
|
+
minZoom: 0,
|
|
221
|
+
maxZoom: 18,
|
|
222
|
+
subdomains: ['a', 'b', 'c'],
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
mapCore.setBasemap({
|
|
226
|
+
id: 'custom-wms',
|
|
227
|
+
name: '自定义 WMS',
|
|
228
|
+
category: 'basemap',
|
|
229
|
+
type: 'wms',
|
|
230
|
+
provider: 'custom',
|
|
231
|
+
serviceUrl: 'https://example.com/geoserver/wms',
|
|
232
|
+
layers: 'workspace:layer',
|
|
233
|
+
parameters: {
|
|
234
|
+
transparent: true,
|
|
235
|
+
format: 'image/png',
|
|
236
|
+
version: '1.1.1',
|
|
179
237
|
},
|
|
180
238
|
})
|
|
181
239
|
```
|
|
182
240
|
|
|
183
|
-
说明:
|
|
184
241
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
242
|
+
方法说明:
|
|
243
|
+
|
|
244
|
+
| 方法 | 参数 | 说明 |
|
|
245
|
+
| --- | --- | --- |
|
|
246
|
+
| `setBasemapById(id)` | 底图 id | 从 `config.basemap.list` 查找底图并切换。会校验 `category / engineSupport / enabled`。 |
|
|
247
|
+
| `setBasemap(payload)` | 底图配置对象 | 直接切换到底图配置。 |
|
|
248
|
+
|
|
249
|
+
常用底图参数:
|
|
250
|
+
|
|
251
|
+
| 参数 | 是否必填 | 说明 |
|
|
252
|
+
| --- | --- | --- |
|
|
253
|
+
| `id` | 建议必填 | 底图唯一 id。 |
|
|
254
|
+
| `name` | 选填 | 底图名称。 |
|
|
255
|
+
| `category` | 建议传 `basemap` | `setBasemapById` 会拒绝非 `basemap` 分类。 |
|
|
256
|
+
| `type` | 自定义服务必填 | `wmts`、`xyz`、`tile`、`wms`。 |
|
|
257
|
+
| `provider` | 选填 | 天地图传 `tianditu`,自定义服务传 `custom`。 |
|
|
258
|
+
| `resourceKey` | 天地图必填 | `vector`、`imagery`、`terrain` 等。 |
|
|
259
|
+
| `annotationResourceKey` | 选填 | 天地图注记资源,如 `vectorLabel`、`imageryLabel`。 |
|
|
260
|
+
| `url` | URL 模板必填 | `wmts/xyz/tile` 使用,支持 `{z}/{x}/{y}` 模板。 |
|
|
261
|
+
| `serviceUrl` | WMS 必填 | WMS 服务地址;也可用 `url`。 |
|
|
262
|
+
| `layers` | WMS 必填 | WMS 图层名。 |
|
|
263
|
+
| `parameters` | 选填 | WMS 附加参数。 |
|
|
264
|
+
| `engineSupport` | 选填 | 支持的引擎列表,如 `['cesium', 'leaflet']`。 |
|
|
265
|
+
|
|
189
266
|
|
|
190
267
|
## BaseGIS 基础能力
|
|
191
268
|
|
|
192
|
-
|
|
269
|
+
这一节列的是 `BaseGIS` 主入口直接提供的基础能力。业务页面优先调用这些方法;图片图层、网格图层、海量点、点位抽稀、等值线、风场等更复杂能力,建议使用后文 `methods` 中对应的 Controller。
|
|
270
|
+
|
|
271
|
+
### 1. 生命周期、实例与引擎切换
|
|
272
|
+
|
|
273
|
+
`BaseGIS` 支持 `cesium` 和 `leaflet` 两种引擎。引擎可以在构造时指定,也可以在 `init()` 时指定。
|
|
193
274
|
|
|
194
275
|
```js
|
|
195
|
-
mapCore
|
|
196
|
-
|
|
276
|
+
const mapCore = new BaseGIS({
|
|
277
|
+
engineType: 'cesium',
|
|
278
|
+
containerId: 'map',
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
// 创建地图实例。
|
|
282
|
+
mapCore.init()
|
|
283
|
+
|
|
284
|
+
// 只修改当前运行时引擎配置,不会自动重建地图实例。
|
|
285
|
+
mapCore.setEngine('leaflet')
|
|
286
|
+
|
|
287
|
+
// 真正切换地图引擎,需要再次 init。
|
|
288
|
+
// init 内部会先销毁旧 adapter,再按新 engineType 创建新地图实例。
|
|
289
|
+
mapCore.init({
|
|
290
|
+
engineType: 'leaflet',
|
|
291
|
+
containerId: 'map',
|
|
292
|
+
})
|
|
197
293
|
|
|
198
|
-
|
|
294
|
+
// 覆盖运行时配置,不会自动重建地图。
|
|
199
295
|
mapCore.setConfig({ view: { defaultSceneMode: '2d' } })
|
|
200
296
|
|
|
297
|
+
// 读取当前地图引擎
|
|
201
298
|
mapCore.getEngineType()
|
|
299
|
+
//获取当前地图配置
|
|
202
300
|
mapCore.getConfig()
|
|
301
|
+
//获取地图实例
|
|
203
302
|
mapCore.getMapInstance()
|
|
303
|
+
// 销毁当前地图实例。
|
|
304
|
+
mapCore.destroy()
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
方法说明:
|
|
308
|
+
|
|
309
|
+
| 方法 | 参数 | 说明 |
|
|
310
|
+
| --- | --- | --- |
|
|
311
|
+
| `init(options)` | `{ container, containerId, engineType }` | 初始化地图。`container` 可传 DOM,`containerId` 可传 DOM id。 |
|
|
312
|
+
| `destroy()` | 无 | 销毁当前地图实例和 adapter。 |
|
|
313
|
+
| `setEngine(engineType)` | `'cesium'/'leaflet'` | 修改当前引擎类型;不自动重建地图。 |
|
|
314
|
+
| `setConfig(config)` | `Object` | 合并运行时配置;不自动重建地图。 |
|
|
315
|
+
| `getEngineType()` | 无 | 返回当前引擎类型。 |
|
|
316
|
+
| `getConfig()` | 无 | 返回当前运行时配置。 |
|
|
317
|
+
| `getMapInstance()` | 无 | 返回底层地图实例:Cesium `viewer` 或 Leaflet `map`。 |
|
|
318
|
+
|
|
319
|
+
#### 推荐的引擎切换写法
|
|
320
|
+
|
|
321
|
+
页面上做 Cesium / Leaflet 切换时,建议把切换动作收敛成一个函数。`setEngine()` 用来更新 `BaseGIS` 内部引擎类型,`init()` 才是真正重建地图。
|
|
322
|
+
|
|
323
|
+
```js
|
|
324
|
+
async function switchEngine(engineType) {
|
|
325
|
+
if (!mapCore || mapCore.getEngineType() === engineType) {
|
|
326
|
+
return
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const result = mapCore.init({
|
|
330
|
+
engineType,
|
|
331
|
+
containerId: 'map',
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
if (!result.success) {
|
|
335
|
+
console.warn(result.message)
|
|
336
|
+
return
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// 地图实例已经重建,业务图层需要用自己的数据源重新加载。
|
|
340
|
+
await reloadBusinessLayers()
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
也可以显式先调用 `setEngine()`:
|
|
345
|
+
|
|
346
|
+
```js
|
|
347
|
+
mapCore.setEngine('leaflet')
|
|
348
|
+
const result = mapCore.init({
|
|
349
|
+
containerId: 'map',
|
|
350
|
+
})
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
两种写法效果一致;如果 `init({ engineType })` 已经传了目标引擎,可以不单独调用 `setEngine()`。
|
|
354
|
+
|
|
355
|
+
#### 切换后的图层处理
|
|
356
|
+
|
|
357
|
+
引擎切换不是把 Cesium 图层“搬到” Leaflet,也不是把 Leaflet 图层“搬到” Cesium。`init()` 重建地图时会销毁旧引擎实例,因此:
|
|
358
|
+
|
|
359
|
+
- `BaseGIS` 的配置会保留,例如 `config / initialView / basemap`。
|
|
360
|
+
- 业务数据应由页面或 store 保存,例如站点数组、图片地址、等值线数据、风场数据。
|
|
361
|
+
- 切换成功后,用这些业务数据重新调用对应 Controller 的 `load/update`,或重新调用 `BaseGIS` 图层方法。
|
|
362
|
+
- Cesium 专有能力在 Leaflet 下不可用,例如 DEM、三维体渲染、三维切片/剖面渲染。
|
|
363
|
+
- 页面层不应直接依赖 Cesium / Leaflet 分支;如果确实要访问底层实例,只在边界很清楚的地方使用 `getMapInstance()`。
|
|
364
|
+
|
|
365
|
+
常见重载示例:
|
|
366
|
+
|
|
367
|
+
```js
|
|
368
|
+
async function reloadBusinessLayers() {
|
|
369
|
+
await imageLayer.update(currentImagePayload)
|
|
370
|
+
await pointLayer.load({ points: currentPoints })
|
|
371
|
+
await contour.load(currentContourPayload)
|
|
372
|
+
|
|
373
|
+
if (mapCore.getEngineType() === 'cesium') {
|
|
374
|
+
mapCore.upsertVolumeLayer(currentVolumePayload)
|
|
375
|
+
}
|
|
376
|
+
}
|
|
204
377
|
```
|
|
205
378
|
|
|
206
|
-
|
|
379
|
+
|
|
380
|
+
### 2. 视角控制与场景模式
|
|
381
|
+
|
|
382
|
+
视角控制分为缩放、重置视角、设置初始视角、场景模式切换、视图状态读取和视图变化监听。
|
|
207
383
|
|
|
208
384
|
```js
|
|
385
|
+
// 放大 / 缩小。
|
|
386
|
+
// Cesium 可传 { distance },Leaflet 可传 { step }。
|
|
209
387
|
mapCore.zoomIn()
|
|
210
388
|
mapCore.zoomOut()
|
|
211
|
-
mapCore.
|
|
389
|
+
mapCore.zoomIn({ distance: 300000 })
|
|
390
|
+
mapCore.zoomOut({ step: 1 })
|
|
212
391
|
|
|
213
|
-
|
|
214
|
-
mapCore.
|
|
215
|
-
mapCore.
|
|
216
|
-
|
|
392
|
+
// 回到配置中的 initialView,也可以传入目标视角覆盖。
|
|
393
|
+
mapCore.resetView()
|
|
394
|
+
mapCore.resetView({
|
|
395
|
+
center: [104, 35],
|
|
396
|
+
height: 3000000,
|
|
397
|
+
zoom: 5,
|
|
398
|
+
pitch: -90,
|
|
399
|
+
})
|
|
217
400
|
|
|
401
|
+
// 设置视角。center / position 均为 [经度, 纬度]。
|
|
218
402
|
mapCore.setInitialView({
|
|
219
403
|
center: [104, 35],
|
|
404
|
+
// Cesium 使用 height。
|
|
220
405
|
height: 3000000,
|
|
406
|
+
// Leaflet 使用 zoom。
|
|
221
407
|
zoom: 5,
|
|
408
|
+
// Cesium 使用 heading / pitch / roll,单位是度。
|
|
409
|
+
heading: 0,
|
|
222
410
|
pitch: -90,
|
|
411
|
+
roll: 0,
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
// 场景模式。Cesium 支持 2d / 2.5d / 3d;Leaflet 只支持 2d。
|
|
415
|
+
mapCore.setSceneMode('3d')
|
|
416
|
+
mapCore.setSceneMode({
|
|
417
|
+
mode: '2d',
|
|
418
|
+
// Cesium morph 动画时长,单位秒。
|
|
419
|
+
duration: 0.4,
|
|
420
|
+
// Cesium 场景切换后是否尽量恢复原视野,默认 true。
|
|
421
|
+
preserveView: true,
|
|
422
|
+
})
|
|
423
|
+
mapCore.getSceneMode()
|
|
424
|
+
|
|
425
|
+
// 获取当前视图边界。
|
|
426
|
+
const boundsResult = mapCore.getViewBounds()
|
|
427
|
+
// boundsResult.data: { west, south, east, north }
|
|
428
|
+
|
|
429
|
+
// 获取当前视图状态。
|
|
430
|
+
const viewStateResult = mapCore.getViewState()
|
|
431
|
+
// Cesium 通常包含 center / bounds / height / heading / pitch / roll / engineType。
|
|
432
|
+
// Leaflet 通常包含 center / bounds / zoom / engineType。
|
|
433
|
+
|
|
434
|
+
// 经纬度转地图容器像素坐标,常用于自定义 HTML 浮层定位。
|
|
435
|
+
const pointResult = mapCore.projectToContainerPoint({
|
|
436
|
+
longitude: 104,
|
|
437
|
+
latitude: 35,
|
|
438
|
+
height: 0,
|
|
223
439
|
})
|
|
440
|
+
// pointResult.data: { x, y }
|
|
224
441
|
```
|
|
225
442
|
|
|
226
|
-
|
|
443
|
+
视图变化监听:
|
|
227
444
|
|
|
228
445
|
```js
|
|
229
|
-
mapCore.
|
|
446
|
+
const viewListener = mapCore.onViewChange({
|
|
447
|
+
// Cesium: camera.moveStart / morphStart;Leaflet: movestart / zoomstart。
|
|
448
|
+
onStart() {},
|
|
230
449
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
450
|
+
// Cesium: camera.changed;Leaflet: move / zoom / resize。
|
|
451
|
+
// 缩放过程中要实时刷新点位样式时,优先用 onChange。
|
|
452
|
+
onChange() {},
|
|
453
|
+
|
|
454
|
+
// Cesium: camera.moveEnd / morphComplete;Leaflet: moveend / zoomend / resize。
|
|
455
|
+
onEnd() {},
|
|
456
|
+
|
|
457
|
+
// Cesium onEnd 延迟,默认 120ms。
|
|
458
|
+
endDelay: 120,
|
|
237
459
|
})
|
|
238
460
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
mapCore.hideLayer({ layerId: 'custom-wmts' })
|
|
242
|
-
mapCore.removeLayer({ layerId: 'custom-wmts' })
|
|
461
|
+
// 组件卸载时移除监听。
|
|
462
|
+
viewListener.data?.off?.()
|
|
243
463
|
```
|
|
244
464
|
|
|
245
|
-
|
|
465
|
+
方法说明:
|
|
466
|
+
|
|
467
|
+
| 方法 | 参数 | 说明 |
|
|
468
|
+
| --- | --- | --- |
|
|
469
|
+
| `zoomIn(payload)` | Cesium `{ distance }`;Leaflet `{ step }` | 放大地图。 |
|
|
470
|
+
| `zoomOut(payload)` | Cesium `{ distance }`;Leaflet `{ step }` | 缩小地图。 |
|
|
471
|
+
| `resetView(payload)` | 视角对象,可选 | 回到初始视角或传入的目标视角。 |
|
|
472
|
+
| `setInitialView(payload)` | `{ center, height, zoom, heading, pitch, roll }` | 设置当前视角。 |
|
|
473
|
+
| `setSceneMode(payload)` | `'2d'/'2.5d'/'3d'` 或 `{ mode, duration, preserveView }` | 切换场景模式。 |
|
|
474
|
+
| `getSceneMode()` | 无 | 获取当前场景模式。 |
|
|
475
|
+
| `getViewBounds()` | 无 | 获取当前视图经纬度边界。 |
|
|
476
|
+
| `getViewState()` | 无 | 获取当前视图状态。 |
|
|
477
|
+
| `onViewChange(payload)` | `{ onStart, onChange, onEnd, endDelay }` | 监听视图变化,返回 `{ off }`。 |
|
|
478
|
+
| `projectToContainerPoint(payload)` | `{ longitude, latitude, height }` | 经纬度投影到地图容器像素坐标。 |
|
|
479
|
+
|
|
480
|
+
### 4. 绘制点、线、面、文字和 Marker
|
|
481
|
+
|
|
482
|
+
这些方法用于轻量绘制和样例验证。大量点位或复杂业务图层请优先使用后文的 `PointLargeLayerController`、`PointDensityController`、`GraphicGroupController` 等控制器。
|
|
483
|
+
|
|
484
|
+
点:
|
|
246
485
|
|
|
247
486
|
```js
|
|
248
487
|
mapCore.drawPoint({
|
|
249
488
|
id: 'point-1',
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
489
|
+
name: '点位',
|
|
490
|
+
// 必填建议:[经度, 纬度]。
|
|
491
|
+
position: [104, 35],
|
|
492
|
+
height: 0,
|
|
493
|
+
// Cesium 使用 pixelSize;Leaflet 使用 radius。
|
|
494
|
+
pixelSize: 10,
|
|
495
|
+
radius: 7,
|
|
496
|
+
color: '#ff4d4f',
|
|
256
497
|
})
|
|
498
|
+
```
|
|
257
499
|
|
|
500
|
+
线:
|
|
501
|
+
|
|
502
|
+
```js
|
|
258
503
|
mapCore.drawLine({
|
|
259
504
|
id: 'line-1',
|
|
505
|
+
name: '连线',
|
|
260
506
|
positions: [
|
|
261
507
|
[103, 34],
|
|
262
508
|
[105, 36],
|
|
263
509
|
],
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
width: 3,
|
|
267
|
-
},
|
|
510
|
+
width: 3,
|
|
511
|
+
color: '#1677ff',
|
|
268
512
|
})
|
|
513
|
+
```
|
|
269
514
|
|
|
515
|
+
面:
|
|
516
|
+
|
|
517
|
+
```js
|
|
270
518
|
mapCore.drawPolygon({
|
|
271
519
|
id: 'polygon-1',
|
|
520
|
+
name: '区域',
|
|
272
521
|
positions: [
|
|
273
522
|
[102, 33],
|
|
274
523
|
[106, 33],
|
|
275
524
|
[106, 36],
|
|
276
525
|
[102, 36],
|
|
277
526
|
],
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
527
|
+
// Cesium 使用 fillColor;Leaflet 主要使用 color / fillOpacity。
|
|
528
|
+
fillColor: 'rgba(22, 119, 255, 0.25)',
|
|
529
|
+
color: '#1677ff',
|
|
530
|
+
outlineWidth: 2,
|
|
531
|
+
fillOpacity: 0.35,
|
|
532
|
+
// Cesium 默认贴地;显式传 height 时按非贴地面绘制。
|
|
533
|
+
height: 0,
|
|
282
534
|
})
|
|
535
|
+
```
|
|
283
536
|
|
|
537
|
+
文字:
|
|
538
|
+
|
|
539
|
+
```js
|
|
284
540
|
mapCore.drawText({
|
|
285
541
|
id: 'text-1',
|
|
286
|
-
|
|
287
|
-
|
|
542
|
+
name: '文字',
|
|
543
|
+
position: [104, 35],
|
|
288
544
|
text: '示例文字',
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
545
|
+
font: '16px Microsoft YaHei',
|
|
546
|
+
color: '#0f2d4d',
|
|
547
|
+
backgroundColor: 'rgba(255,255,255,0.7)',
|
|
548
|
+
// 默认 center/bottom,也可以传 left/top/right/bottom。
|
|
549
|
+
textAnchor: {
|
|
550
|
+
horizontal: 'center',
|
|
551
|
+
vertical: 'bottom',
|
|
292
552
|
},
|
|
553
|
+
textOffset: [0, 0],
|
|
293
554
|
})
|
|
555
|
+
```
|
|
294
556
|
|
|
557
|
+
图片 Marker:
|
|
558
|
+
|
|
559
|
+
```js
|
|
295
560
|
mapCore.addMarker({
|
|
296
561
|
id: 'marker-1',
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
562
|
+
name: '站点',
|
|
563
|
+
position: [104, 35],
|
|
564
|
+
iconUrl: '/marker.png',
|
|
565
|
+
iconSize: [32, 32],
|
|
566
|
+
// 也支持 iconWidth / iconHeight。
|
|
567
|
+
iconAnchor: [16, 32],
|
|
568
|
+
iconOffset: [0, 0],
|
|
569
|
+
label: '站点名称',
|
|
302
570
|
})
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
清理图形:
|
|
303
574
|
|
|
575
|
+
```js
|
|
304
576
|
mapCore.removeGraphic({ id: 'marker-1' })
|
|
577
|
+
mapCore.removeGraphic('marker-1')
|
|
305
578
|
mapCore.clearGraphics()
|
|
306
579
|
```
|
|
307
580
|
|
|
308
|
-
|
|
581
|
+
方法说明:
|
|
582
|
+
|
|
583
|
+
| 方法 | 参数 | 说明 |
|
|
584
|
+
| --- | --- | --- |
|
|
585
|
+
| `drawPoint(payload)` | 点配置 | 绘制点。 |
|
|
586
|
+
| `drawLine(payload)` | 线配置 | 绘制线。 |
|
|
587
|
+
| `drawPolygon(payload)` | 面配置 | 绘制面。 |
|
|
588
|
+
| `drawText(payload)` | 文字配置 | 绘制文字。 |
|
|
589
|
+
| `addMarker(payload)` | Marker 配置 | 绘制图片 Marker;未传 `iconUrl` 时降级为点。 |
|
|
590
|
+
| `removeGraphic(payload)` | 图形 id 或 `{ id }` | 删除指定图形。 |
|
|
591
|
+
| `clearGraphics()` | 无 | 清空通过基础绘制方法创建的图形。 |
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
### 6. 点击事件
|
|
596
|
+
|
|
597
|
+
`onClick` 注册地图点击事件;`offClick` 移除当前点击监听。当前每个 adapter 只保留一个基础点击监听,重复调用 `onClick` 会先移除旧监听。
|
|
309
598
|
|
|
310
599
|
```js
|
|
311
|
-
|
|
312
|
-
id: 'station-click',
|
|
600
|
+
mapCore.onClick({
|
|
313
601
|
callback(event) {
|
|
314
|
-
// event 中通常包含 longitude / latitude / pickedObject 等信息,具体字段与引擎有关。
|
|
315
602
|
console.log(event)
|
|
316
603
|
},
|
|
317
604
|
})
|
|
318
605
|
|
|
319
|
-
mapCore.offClick(
|
|
320
|
-
|
|
321
|
-
const point = mapCore.projectToContainerPoint({
|
|
322
|
-
longitude: 104,
|
|
323
|
-
latitude: 35,
|
|
324
|
-
height: 0,
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
const bounds = mapCore.getViewBounds()
|
|
328
|
-
const viewListener = mapCore.onViewChange({
|
|
329
|
-
onStart() {},
|
|
330
|
-
onEnd() {},
|
|
331
|
-
})
|
|
332
|
-
viewListener.data?.off?.()
|
|
606
|
+
mapCore.offClick()
|
|
333
607
|
```
|
|
334
608
|
|
|
335
|
-
|
|
609
|
+
Cesium 点击空地时的事件结构:
|
|
336
610
|
|
|
337
611
|
```js
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
612
|
+
{
|
|
613
|
+
clickType: 'coordinate',
|
|
614
|
+
engineType: 'cesium',
|
|
615
|
+
coordinates: {
|
|
616
|
+
longitude: 104,
|
|
617
|
+
latitude: 35,
|
|
618
|
+
height: 0,
|
|
619
|
+
},
|
|
620
|
+
}
|
|
346
621
|
```
|
|
347
622
|
|
|
348
|
-
|
|
623
|
+
Cesium 点击 Entity 时的事件结构:
|
|
349
624
|
|
|
350
|
-
|
|
625
|
+
```js
|
|
626
|
+
{
|
|
627
|
+
clickType: 'entity',
|
|
628
|
+
engineType: 'cesium',
|
|
629
|
+
coordinates: {
|
|
630
|
+
longitude: 104,
|
|
631
|
+
latitude: 35,
|
|
632
|
+
height: 0,
|
|
633
|
+
},
|
|
634
|
+
target: {
|
|
635
|
+
id: 'point-1',
|
|
636
|
+
name: '点位',
|
|
637
|
+
entityType: 'entity',
|
|
638
|
+
},
|
|
639
|
+
}
|
|
640
|
+
```
|
|
351
641
|
|
|
352
|
-
|
|
642
|
+
Leaflet 当前返回坐标点击:
|
|
353
643
|
|
|
354
644
|
```js
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
resourceKey: 'imagery',
|
|
366
|
-
category: 'basemap',
|
|
367
|
-
engineSupport: ['cesium', 'leaflet'],
|
|
368
|
-
})
|
|
645
|
+
{
|
|
646
|
+
clickType: 'coordinate',
|
|
647
|
+
engineType: 'leaflet',
|
|
648
|
+
coordinates: {
|
|
649
|
+
longitude: 104,
|
|
650
|
+
latitude: 35,
|
|
651
|
+
height: 0,
|
|
652
|
+
},
|
|
653
|
+
}
|
|
654
|
+
```
|
|
369
655
|
|
|
370
|
-
|
|
371
|
-
id: 'geoserver-tile',
|
|
372
|
-
name: 'GeoServer 瓦片',
|
|
373
|
-
url: 'https://example.com/tiles/{z}/{x}/{y}.png',
|
|
374
|
-
})
|
|
656
|
+
说明:
|
|
375
657
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
serviceUrl: 'https://example.com/geoserver/wms',
|
|
379
|
-
layers: 'workspace:layer',
|
|
380
|
-
parameters: {
|
|
381
|
-
transparent: true,
|
|
382
|
-
format: 'image/png',
|
|
383
|
-
},
|
|
384
|
-
})
|
|
658
|
+
- 基础 `onClick` 适合地图空白点击、简单 Entity 点击。
|
|
659
|
+
- 海量点、点位抽稀等图层自己的点击事件,应使用对应 Controller 的 `onClick` 参数。
|
|
385
660
|
|
|
386
|
-
const wmts = createWmtsLayer({
|
|
387
|
-
id: 'wmts-layer',
|
|
388
|
-
url: 'https://example.com/wmts?...TILEMATRIX={z}&TILEROW={y}&TILECOL={x}',
|
|
389
|
-
layer: 'workspace:layer',
|
|
390
|
-
tileMatrixSet: 'EPSG:3857',
|
|
391
|
-
})
|
|
392
|
-
```
|
|
393
661
|
|
|
394
662
|
## GraphicGroupController
|
|
395
663
|
|
|
@@ -430,205 +698,1466 @@ graphics.getState()
|
|
|
430
698
|
|
|
431
699
|
## ImageLayerController
|
|
432
700
|
|
|
433
|
-
|
|
701
|
+
用于管理一个图片覆盖层。所有更新都走 `update(payload)`;页面有很多时次数据时,自己维护数据列表,然后把当前时次的数据传给 `update`。
|
|
702
|
+
|
|
703
|
+
先创建控制器。这里是控制器级默认参数,后续每次 `update(payload)` 都可以覆盖这些默认值:
|
|
434
704
|
|
|
435
705
|
```js
|
|
436
706
|
import { ImageLayerController } from '@3clear/basegis/methods'
|
|
437
707
|
|
|
438
708
|
const imageLayer = new ImageLayerController({
|
|
709
|
+
// 必填:BaseGIS 实例。也可以写 baseGIS: mapCore。
|
|
439
710
|
mapCore,
|
|
711
|
+
|
|
712
|
+
// 选填:图层 id。不传时默认 image-layer-default。
|
|
713
|
+
// 后续 show / hide / destroy 会按这个 id 找图层。
|
|
440
714
|
layerId: 'radar-image',
|
|
715
|
+
|
|
716
|
+
// 选填:默认透明度,范围通常是 0 - 1。不传时默认 0.85。
|
|
441
717
|
opacity: 0.85,
|
|
718
|
+
|
|
719
|
+
// 选填:默认图片四至范围。
|
|
720
|
+
// 如果 update(payload) 里传 imageUrl,但没有传 area,就会使用这里的 defaultArea。
|
|
442
721
|
defaultArea: {
|
|
443
722
|
startLon: 73,
|
|
444
723
|
startLat: 18,
|
|
445
724
|
endLon: 135,
|
|
446
725
|
endLat: 54,
|
|
447
726
|
},
|
|
727
|
+
|
|
728
|
+
// 选填:默认图片类型。color 表示图片已经填色;grayscale 表示灰度图需要运行时着色。
|
|
729
|
+
imageSourceType: 'color',
|
|
730
|
+
|
|
731
|
+
// 选填:默认小数位,网格标注或探针显示数值时使用。
|
|
732
|
+
decimalPlaces: 2,
|
|
448
733
|
})
|
|
734
|
+
```
|
|
449
735
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
736
|
+
### 1. 普通图片
|
|
737
|
+
|
|
738
|
+
只显示一张已经处理好的 PNG/JPG。适合雷达图、云图、已填色格点图。
|
|
739
|
+
|
|
740
|
+
```js
|
|
741
|
+
await imageLayer.update({
|
|
742
|
+
// 选填:当前数据 id,用于控制器内部记录 activeItem。
|
|
743
|
+
id: 'radar-202607010800',
|
|
744
|
+
|
|
745
|
+
// 选填:当前数据名称,用于状态展示。
|
|
746
|
+
name: '08:00 雷达',
|
|
747
|
+
|
|
748
|
+
// 必填:图片地址。普通图片模式必须传 imageUrl。
|
|
749
|
+
imageUrl: '/data/radar/202607010800.png',
|
|
750
|
+
|
|
751
|
+
// 必填:图片四至范围。只要传 imageUrl,就必须能确定 area。
|
|
752
|
+
area: {
|
|
753
|
+
// 必填:左边界经度。
|
|
754
|
+
startLon: 73,
|
|
755
|
+
// 必填:下边界纬度。
|
|
756
|
+
startLat: 18,
|
|
757
|
+
// 必填:右边界经度。
|
|
758
|
+
endLon: 135,
|
|
759
|
+
// 必填:上边界纬度。
|
|
760
|
+
endLat: 54,
|
|
761
|
+
},
|
|
762
|
+
|
|
763
|
+
// 选填:color 表示图片本身已经填色,不需要再按色带处理。
|
|
764
|
+
imageSourceType: 'color',
|
|
765
|
+
|
|
766
|
+
// 选填:透明度,覆盖控制器默认 opacity。
|
|
767
|
+
opacity: 0.8,
|
|
768
|
+
|
|
769
|
+
// 选填:是否显示图层。不传时使用控制器当前 visible 状态。
|
|
770
|
+
visible: true,
|
|
771
|
+
})
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
### 2. 图片 + TIF
|
|
775
|
+
|
|
776
|
+
图片负责显示,TIF 负责鼠标探针、网格取值、网格注记。
|
|
777
|
+
|
|
778
|
+
```js
|
|
779
|
+
await imageLayer.update({
|
|
780
|
+
// 选填:当前数据 id。
|
|
781
|
+
id: 'temper-202607010900',
|
|
782
|
+
|
|
783
|
+
// 选填:当前数据名称。
|
|
784
|
+
name: '09:00 温度图',
|
|
785
|
+
|
|
786
|
+
// 必填:显示用图片地址。
|
|
787
|
+
imageUrl: '/data/temper/202607010900.png',
|
|
788
|
+
|
|
789
|
+
// 必填:取值用 TIF 地址。开启探针或注记时必须有可取值数据。
|
|
790
|
+
tifUrl: '/data/temper/202607010900.tif',
|
|
791
|
+
|
|
792
|
+
// 必填:图片四至范围。
|
|
793
|
+
area: {
|
|
794
|
+
startLon: 73,
|
|
795
|
+
startLat: 18,
|
|
796
|
+
endLon: 135,
|
|
797
|
+
endLat: 54,
|
|
798
|
+
},
|
|
799
|
+
|
|
800
|
+
// 选填:显示图是已经填色的图片。
|
|
801
|
+
imageSourceType: 'color',
|
|
802
|
+
|
|
803
|
+
// 选填:是否开启鼠标探针。依赖 tifUrl。
|
|
804
|
+
showProbe: true,
|
|
805
|
+
|
|
806
|
+
// 选填:是否显示网格注记。依赖 tifUrl。
|
|
807
|
+
showLabel: true,
|
|
808
|
+
|
|
809
|
+
// 选填:探针或注记数值的小数位。
|
|
810
|
+
decimalPlaces: 1,
|
|
811
|
+
|
|
812
|
+
// 选填:透明度。
|
|
813
|
+
opacity: 0.85,
|
|
814
|
+
})
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
### 3. 灰度图 + 色带
|
|
818
|
+
|
|
819
|
+
灰度图不是已经填好颜色的图,需要传 `imageSourceType: 'grayscale'` 和 `colorize`。
|
|
820
|
+
|
|
821
|
+
```js
|
|
822
|
+
await imageLayer.update({
|
|
823
|
+
// 选填:当前数据 id。
|
|
824
|
+
id: 'pressure-gray',
|
|
825
|
+
|
|
826
|
+
// 选填:当前数据名称。
|
|
827
|
+
name: '气压灰度图',
|
|
828
|
+
|
|
829
|
+
// 必填:灰度图地址。
|
|
830
|
+
imageUrl: '/data/pressure-gray.png',
|
|
831
|
+
|
|
832
|
+
// 必填:灰度图四至范围。
|
|
833
|
+
area: {
|
|
834
|
+
startLon: -180,
|
|
835
|
+
startLat: -90,
|
|
836
|
+
endLon: 180,
|
|
837
|
+
endLat: 90,
|
|
838
|
+
},
|
|
839
|
+
|
|
840
|
+
// 必填:灰度图必须声明为 grayscale,适配层才会按 colorize 着色。
|
|
841
|
+
imageSourceType: 'grayscale',
|
|
842
|
+
|
|
843
|
+
// 选填:是否按切片方式处理大图。大范围灰度图建议开启。
|
|
844
|
+
isSplit: true,
|
|
845
|
+
|
|
846
|
+
// 选填:切分网格数量,isSplit 为 true 时使用。
|
|
847
|
+
gridTotal: 4,
|
|
848
|
+
|
|
849
|
+
// 选填:探针或注记数值的小数位。
|
|
850
|
+
decimalPlaces: 1,
|
|
851
|
+
|
|
852
|
+
// 必填:灰度图着色配置。
|
|
853
|
+
colorize: {
|
|
854
|
+
// 必填:灰度值或数据值最小值。
|
|
855
|
+
minValue: 960,
|
|
856
|
+
// 必填:灰度值或数据值最大值。
|
|
857
|
+
maxValue: 1040,
|
|
858
|
+
// 选填:无效值,命中该值时不参与着色。
|
|
859
|
+
noDataValue: 255,
|
|
860
|
+
// 必填:色带颜色。支持 16 进制字符串、rgb 字符串或 RGB 数组。
|
|
861
|
+
colors: ['#2639a7', '#2faaf3', '#8ee5b2', '#fd9919', '#fb422d'],
|
|
862
|
+
},
|
|
863
|
+
})
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
`loadGrayImage` 的灰度值换算规则:
|
|
867
|
+
|
|
868
|
+
```js
|
|
869
|
+
业务值 = (灰度值 - grayMinValue) / (grayMaxValue - grayMinValue) * (maxValue - minValue) + minValue
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
所以灰度图要表达真实业务值时,建议显式传 `minValue / maxValue`。如果只写 `colorize: true`,会使用默认范围 `minValue: 0`、`maxValue: 1`、`grayMinValue: 1`、`grayMaxValue: 254`,只适合临时预览,不适合正式业务图层。
|
|
873
|
+
|
|
874
|
+
`loadGrayImage` 支持两种写法:
|
|
875
|
+
|
|
876
|
+
```js
|
|
877
|
+
await gridLayer.loadGrayImage({
|
|
878
|
+
imageUrl: '/data/grid/temp-gray.png',
|
|
879
|
+
area,
|
|
880
|
+
colorize: {
|
|
881
|
+
minValue: -20,
|
|
882
|
+
maxValue: 50,
|
|
883
|
+
colors: ['#2639a7', '#2faaf3', '#8ee5b2', '#fd9919', '#fb422d'],
|
|
884
|
+
},
|
|
885
|
+
})
|
|
886
|
+
|
|
887
|
+
await gridLayer.loadGrayImage({
|
|
888
|
+
imageUrl: '/data/grid/temp-gray.png',
|
|
889
|
+
area,
|
|
890
|
+
minValue: -20,
|
|
891
|
+
maxValue: 50,
|
|
892
|
+
grayMinValue: 1,
|
|
893
|
+
grayMaxValue: 254,
|
|
894
|
+
colors: ['#2639a7', '#2faaf3', '#8ee5b2', '#fd9919', '#fb422d'],
|
|
895
|
+
})
|
|
896
|
+
```
|
|
897
|
+
### 4. 纯 TIF
|
|
898
|
+
|
|
899
|
+
只传 TIF,不传图片。适合数据本身带地理范围、需要按 TIF 渲染的场景。
|
|
900
|
+
|
|
901
|
+
```js
|
|
902
|
+
await imageLayer.update({
|
|
903
|
+
// 选填:当前数据 id。
|
|
904
|
+
id: 'rain-tif',
|
|
905
|
+
|
|
906
|
+
// 必填建议:纯 TIF 模式下显式清空 imageUrl,避免沿用上一次图片。
|
|
907
|
+
imageUrl: '',
|
|
908
|
+
|
|
909
|
+
// 必填:TIF 地址。
|
|
910
|
+
tifUrl: '/data/rain.tif',
|
|
911
|
+
|
|
912
|
+
// 选填:是否按默认色带着色。需要更精细控制时传 colorize 对象。
|
|
913
|
+
colorize: true,
|
|
914
|
+
|
|
915
|
+
// 选填:是否开启鼠标探针。
|
|
916
|
+
showProbe: true,
|
|
917
|
+
})
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
### 5. 很多时次数据怎么更新
|
|
921
|
+
|
|
922
|
+
很多数据不要用 `next()`。页面维护数组,点击或时间轴变化时,把当前项传给 `update()`。
|
|
923
|
+
|
|
924
|
+
```js
|
|
925
|
+
const imageDataSources = [
|
|
926
|
+
{
|
|
927
|
+
// 必填:业务自己的时次 key。
|
|
928
|
+
key: '202607010800',
|
|
929
|
+
// 必填:当前时次图片地址。
|
|
930
|
+
imageUrl: '/data/radar/202607010800.png',
|
|
931
|
+
},
|
|
932
|
+
{
|
|
933
|
+
key: '202607010900',
|
|
934
|
+
imageUrl: '/data/radar/202607010900.png',
|
|
935
|
+
},
|
|
936
|
+
]
|
|
937
|
+
|
|
938
|
+
async function updateImageByTime(timeKey) {
|
|
939
|
+
const source = imageDataSources.find((item) => item.key === timeKey)
|
|
940
|
+
if (!source) return
|
|
941
|
+
|
|
942
|
+
await imageLayer.update({
|
|
943
|
+
// 选填:用时次 key 作为当前数据 id。
|
|
944
|
+
id: source.key,
|
|
945
|
+
|
|
946
|
+
// 必填:当前时次图片地址。
|
|
947
|
+
imageUrl: source.imageUrl,
|
|
948
|
+
|
|
949
|
+
// 必填:图片四至范围。
|
|
950
|
+
area: {
|
|
951
|
+
startLon: 73,
|
|
952
|
+
startLat: 18,
|
|
458
953
|
endLon: 135,
|
|
459
954
|
endLat: 54,
|
|
460
955
|
},
|
|
461
|
-
|
|
956
|
+
|
|
957
|
+
// 选填:普通已填色图片使用 color。
|
|
958
|
+
imageSourceType: 'color',
|
|
959
|
+
|
|
960
|
+
// 选填:更新时间后直接显示图层。
|
|
961
|
+
visible: true,
|
|
962
|
+
})
|
|
963
|
+
}
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
### 6. 控制方法
|
|
967
|
+
|
|
968
|
+
`ImageLayerController` 除了 `update(payload)`,还提供显隐、销毁、状态读取和兼容旧集合模式的方法。
|
|
969
|
+
|
|
970
|
+
```js
|
|
971
|
+
// 创建或更新当前图片图层。
|
|
972
|
+
await imageLayer.update({
|
|
973
|
+
imageUrl: '/data/radar/202607010800.png',
|
|
974
|
+
area: {
|
|
975
|
+
startLon: 73,
|
|
976
|
+
startLat: 18,
|
|
977
|
+
endLon: 135,
|
|
978
|
+
endLat: 54,
|
|
979
|
+
},
|
|
980
|
+
})
|
|
981
|
+
|
|
982
|
+
// 隐藏当前控制器对应的图片图层。
|
|
983
|
+
imageLayer.hide()
|
|
984
|
+
|
|
985
|
+
// 重新显示当前控制器对应的图片图层。
|
|
986
|
+
imageLayer.show()
|
|
987
|
+
|
|
988
|
+
// 读取当前控制器状态。
|
|
989
|
+
const state = imageLayer.getState()
|
|
990
|
+
|
|
991
|
+
// 移除地图上的图片图层,并清空控制器本地状态。
|
|
992
|
+
imageLayer.destroy()
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
如果一个控制器需要临时操作其他图片图层,可以传入 `layerId`;也可以直接传字符串:
|
|
996
|
+
|
|
997
|
+
```js
|
|
998
|
+
imageLayer.show({ layerId: 'radar-image' })
|
|
999
|
+
imageLayer.hide('radar-image')
|
|
1000
|
+
imageLayer.destroy({ layerId: 'radar-image' })
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
方法总表:
|
|
1004
|
+
|
|
1005
|
+
| 方法 | 参数 | 返回值 | 说明 |
|
|
1006
|
+
| --- | --- | --- | --- |
|
|
1007
|
+
| `mount(target)` | `BaseGIS` 实例 | `Result` | 绑定 `BaseGIS`。构造时已传 `mapCore/baseGIS` 时通常不需要手动调用。 |
|
|
1008
|
+
| `update(payload)` | 图片图层数据 | `Promise<Result>` | 推荐主入口。创建或更新当前图片图层,支持普通图片、图片+TIF、灰度图+色带、纯 TIF。 |
|
|
1009
|
+
| `show(payload)` | 可选 `layerId` 或 `{ layerId }` | `Result` | 显示图片图层。成功后控制器 `visible` 变为 `true`。 |
|
|
1010
|
+
| `hide(payload)` | 可选 `layerId` 或 `{ layerId }` | `Result` | 隐藏图片图层。成功后控制器 `visible` 变为 `false`。 |
|
|
1011
|
+
| `destroy(payload)` | 可选 `layerId` 或 `{ layerId }` | `Result` | 移除图片图层,并清空 `items / activeIndex / layerType / currentPayload`。如果地图已销毁,只清本地状态。 |
|
|
1012
|
+
| `getState()` | 无 | `Object` | 获取控制器状态。 |
|
|
1013
|
+
| `load(items, options)` | 图片数组、可选 `{ index, visible }` | `Promise<Result>` | 兼容旧的图片集合加载方式,会加载 `items[index]`。 |
|
|
1014
|
+
| `switchTo(target)` | 图片索引或图片 id | `Promise<Result>` | 在 `load` 后的本地图片集合中切换当前图片。 |
|
|
1015
|
+
| `next()` | 无 | `Promise<Result>` | 切到下一张本地图片。只适合本地小数组演示,不推荐作为业务时次更新主路径。 |
|
|
1016
|
+
| `prev()` | 无 | `Promise<Result>` | 切到上一张本地图片。只适合本地小数组演示,不推荐作为业务时次更新主路径。 |
|
|
1017
|
+
|
|
1018
|
+
`getState()` 返回结构:
|
|
1019
|
+
|
|
1020
|
+
```js
|
|
1021
|
+
{
|
|
1022
|
+
mounted: true,
|
|
1023
|
+
engineType: 'cesium',
|
|
1024
|
+
layerType: 'image',
|
|
1025
|
+
visible: true,
|
|
1026
|
+
total: 1,
|
|
1027
|
+
activeIndex: 0,
|
|
1028
|
+
activeItem: {
|
|
1029
|
+
id: 'radar-202607010800',
|
|
1030
|
+
imageUrl: '/data/radar/202607010800.png',
|
|
1031
|
+
},
|
|
1032
|
+
payload: {
|
|
1033
|
+
layerId: 'radar-image',
|
|
1034
|
+
imageUrl: '/data/radar/202607010800.png',
|
|
1035
|
+
opacity: 0.85,
|
|
1036
|
+
},
|
|
1037
|
+
}
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
### 参数总表
|
|
1041
|
+
|
|
1042
|
+
| 参数 | 是否必填 | 说明 |
|
|
1043
|
+
| --- | --- | --- |
|
|
1044
|
+
| `mapCore` / `baseGIS` | 创建控制器必填 | `BaseGIS` 实例。 |
|
|
1045
|
+
| `layerId` | 选填 | 图层 id,不传默认 `image-layer-default`。 |
|
|
1046
|
+
| `defaultArea` | 选填 | 默认图片范围,`update` 未传 `area` 时使用。 |
|
|
1047
|
+
| `id` | 选填 | 当前数据 id,便于状态记录。 |
|
|
1048
|
+
| `name` | 选填 | 当前数据名称,便于页面展示。 |
|
|
1049
|
+
| `imageUrl` | 普通图片、灰度图、图片+TIF 必填 | 图片地址。纯 TIF 模式建议传空字符串清掉旧图片。 |
|
|
1050
|
+
| `tifUrl` | 纯 TIF、图片+TIF 必填 | GeoTIFF 地址,用于渲染、探针或网格注记。 |
|
|
1051
|
+
| `area` | 传 `imageUrl` 时必填 | 图片范围:`startLon / startLat / endLon / endLat`。 |
|
|
1052
|
+
| `imageSourceType` | 灰度图必填,其他选填 | `color` 表示已填色图片;`grayscale` 表示灰度图。 |
|
|
1053
|
+
| `colorize` | 灰度图必填,TIF 着色选填 | 色带配置,或传 `true` 使用默认着色。 |
|
|
1054
|
+
| `colorize.minValue` | 灰度图必填 | 色带映射最小值。 |
|
|
1055
|
+
| `colorize.maxValue` | 灰度图必填 | 色带映射最大值。 |
|
|
1056
|
+
| `colorize.noDataValue` | 选填 | 无效值。 |
|
|
1057
|
+
| `colorize.colors` | 灰度图必填 | 色带颜色数组。 |
|
|
1058
|
+
| `opacity` | 选填 | 透明度,通常 0 - 1。 |
|
|
1059
|
+
| `visible` | 选填 | 是否显示图层。 |
|
|
1060
|
+
| `showProbe` | 选填 | 是否开启鼠标探针,通常依赖 `tifUrl`。 |
|
|
1061
|
+
| `showLabel` | 选填 | 是否显示网格注记,通常依赖 `tifUrl`。 |
|
|
1062
|
+
| `decimalPlaces` | 选填 | 探针或注记数值小数位。 |
|
|
1063
|
+
| `isSplit` | 选填 | 是否切片处理大图。 |
|
|
1064
|
+
| `gridTotal` | 选填 | 切片网格数量。 |
|
|
1065
|
+
| `tileSize` | 选填 | 切片尺寸。 |
|
|
1066
|
+
|
|
1067
|
+
兼容方法:
|
|
1068
|
+
|
|
1069
|
+
- `load(items, { index, visible })`:兼容旧的图片集合加载方式,会把 `items[index]` 写入当前图层。
|
|
1070
|
+
- `switchTo(idOrIndex)`:在已加载的 `items` 内切换到某一项。
|
|
1071
|
+
- `next() / prev()`:只适合本地小数组演示,不推荐作为业务时次更新主路径。
|
|
1072
|
+
|
|
1073
|
+
## GridLayerController
|
|
1074
|
+
|
|
1075
|
+
用于 TIF 网格、灰度图网格、外部数值网格。
|
|
1076
|
+
|
|
1077
|
+
```js
|
|
1078
|
+
import { GridLayerController } from '@3clear/basegis/methods'
|
|
1079
|
+
|
|
1080
|
+
const gridLayer = new GridLayerController({
|
|
1081
|
+
mapCore,
|
|
1082
|
+
layerId: 'temperature-grid',
|
|
1083
|
+
showLabel: true,
|
|
1084
|
+
showProbe: true,
|
|
1085
|
+
decimalPlaces: 1,
|
|
1086
|
+
})
|
|
1087
|
+
|
|
1088
|
+
await gridLayer.loadTif({
|
|
1089
|
+
tifUrl: '/data/grid/temp.tif',
|
|
1090
|
+
colorize: true,
|
|
1091
|
+
})
|
|
1092
|
+
|
|
1093
|
+
await gridLayer.loadGrayImage({
|
|
1094
|
+
imageUrl: '/data/grid/temp-gray.png',
|
|
1095
|
+
area: {
|
|
1096
|
+
startLon: 73,
|
|
1097
|
+
startLat: 18,
|
|
1098
|
+
endLon: 135,
|
|
1099
|
+
endLat: 54,
|
|
1100
|
+
},
|
|
1101
|
+
// 灰度图需要把灰度值映射成业务值,再按业务值找色带。
|
|
1102
|
+
colorize: {
|
|
1103
|
+
// 必填建议:业务值最小值。
|
|
1104
|
+
minValue: -20,
|
|
1105
|
+
// 必填建议:业务值最大值。
|
|
1106
|
+
maxValue: 50,
|
|
1107
|
+
// 选填:灰度有效最小值,不传默认 1。
|
|
1108
|
+
grayMinValue: 1,
|
|
1109
|
+
// 选填:灰度有效最大值,不传默认 254。
|
|
1110
|
+
grayMaxValue: 254,
|
|
1111
|
+
// 选填:无效灰度值,不传默认 255。
|
|
1112
|
+
noDataValue: 255,
|
|
1113
|
+
},
|
|
1114
|
+
})
|
|
1115
|
+
|
|
1116
|
+
await gridLayer.loadData({
|
|
1117
|
+
imageGridData: [
|
|
1118
|
+
[12.1, 13.4],
|
|
1119
|
+
[14.2, 15.6],
|
|
1120
|
+
],
|
|
1121
|
+
area: {
|
|
1122
|
+
startLon: 100,
|
|
1123
|
+
startLat: 30,
|
|
1124
|
+
endLon: 110,
|
|
1125
|
+
endLat: 40,
|
|
1126
|
+
},
|
|
1127
|
+
})
|
|
1128
|
+
|
|
1129
|
+
gridLayer.update({ opacity: 0.7 })
|
|
1130
|
+
gridLayer.hide()
|
|
1131
|
+
gridLayer.show()
|
|
1132
|
+
gridLayer.destroy()
|
|
1133
|
+
```
|
|
1134
|
+
|
|
1135
|
+
## 三维体渲染
|
|
1136
|
+
|
|
1137
|
+
三维体渲染是 Cesium 专有能力,直接通过 `BaseGIS` 调用。Leaflet 调用时会返回不支持结果,不会抛出破坏页面的异常。
|
|
1138
|
+
|
|
1139
|
+
适合体数据云图、污染物三维浓度、气象三维场等需要在一个三维盒子内做体积采样的场景。
|
|
1140
|
+
|
|
1141
|
+
### 基础用法
|
|
1142
|
+
|
|
1143
|
+
```js
|
|
1144
|
+
const result = mapCore.upsertVolumeLayer({
|
|
1145
|
+
// 建议必填:图层唯一 id。再次使用同一个 layerId 调用会覆盖旧体渲染层。
|
|
1146
|
+
layerId: 'volume-demo',
|
|
1147
|
+
|
|
1148
|
+
// 必填:体数据一维数组,长度通常为 rows * cols * heights。
|
|
1149
|
+
data: volumeValues,
|
|
1150
|
+
|
|
1151
|
+
// 必填:体数据范围和网格尺寸。
|
|
1152
|
+
option: {
|
|
1153
|
+
// 经度范围。
|
|
1154
|
+
xmin: 110,
|
|
1155
|
+
xmax: 120,
|
|
1156
|
+
// 纬度范围。
|
|
1157
|
+
ymin: 30,
|
|
1158
|
+
ymax: 40,
|
|
1159
|
+
// 高度范围,单位按业务数据约定。
|
|
1160
|
+
zmin: 0,
|
|
1161
|
+
zmax: 10000,
|
|
1162
|
+
// 纬向、经向、高度向网格数量。
|
|
1163
|
+
rows: 100,
|
|
1164
|
+
cols: 100,
|
|
1165
|
+
heights: 30,
|
|
1166
|
+
},
|
|
1167
|
+
|
|
1168
|
+
// 选填:体渲染 shader 参数,可后续单独更新。
|
|
1169
|
+
parameters: {
|
|
1170
|
+
// 采样阈值。值越小,通常显示范围越少;具体效果和数据归一化有关。
|
|
1171
|
+
threshold: 0.3,
|
|
1172
|
+
// 光线步进采样次数。越大越细腻,也越耗性能。
|
|
1173
|
+
steps: 100,
|
|
1174
|
+
// x/y/z 三个方向裁切位置,默认 -0.5 表示不裁切。
|
|
1175
|
+
xCut: -0.5,
|
|
1176
|
+
yCut: -0.5,
|
|
1177
|
+
zCut: -0.5,
|
|
1178
|
+
},
|
|
1179
|
+
|
|
1180
|
+
// 选填:初始是否显示。
|
|
1181
|
+
visible: true,
|
|
1182
|
+
})
|
|
1183
|
+
|
|
1184
|
+
if (!result.success) {
|
|
1185
|
+
console.warn(result.message)
|
|
1186
|
+
}
|
|
1187
|
+
```
|
|
1188
|
+
|
|
1189
|
+
### 更新参数
|
|
1190
|
+
|
|
1191
|
+
更新透明阈值、步进数、裁切面时,不需要重新加载体数据,直接更新参数即可。
|
|
1192
|
+
|
|
1193
|
+
```js
|
|
1194
|
+
mapCore.updateVolumeLayerParameters({
|
|
1195
|
+
layerId: 'volume-demo',
|
|
1196
|
+
parameters: {
|
|
1197
|
+
threshold: 0.5,
|
|
1198
|
+
steps: 180,
|
|
1199
|
+
zCut: 0.1,
|
|
1200
|
+
},
|
|
1201
|
+
})
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
### 更新数据
|
|
1205
|
+
|
|
1206
|
+
更新数据或空间范围时,继续使用同一个 `layerId` 调用 `upsertVolumeLayer`。适配层会先移除旧 Primitive,再创建新的体渲染层。
|
|
1207
|
+
|
|
1208
|
+
```js
|
|
1209
|
+
mapCore.upsertVolumeLayer({
|
|
1210
|
+
layerId: 'volume-demo',
|
|
1211
|
+
data: nextVolumeValues,
|
|
1212
|
+
option: nextVolumeOption,
|
|
1213
|
+
parameters: currentParameters,
|
|
1214
|
+
})
|
|
1215
|
+
```
|
|
1216
|
+
|
|
1217
|
+
### 显隐、定位和移除
|
|
1218
|
+
|
|
1219
|
+
```js
|
|
1220
|
+
mapCore.hideVolumeLayer({ layerId: 'volume-demo' })
|
|
1221
|
+
mapCore.showVolumeLayer({ layerId: 'volume-demo' })
|
|
1222
|
+
mapCore.flyToVolumeLayer({ layerId: 'volume-demo', duration: 0.8 })
|
|
1223
|
+
mapCore.removeVolumeLayer({ layerId: 'volume-demo' })
|
|
1224
|
+
|
|
1225
|
+
const stateResult = mapCore.getVolumeLayerState({ layerId: 'volume-demo' })
|
|
1226
|
+
console.log(stateResult.data)
|
|
1227
|
+
```
|
|
1228
|
+
|
|
1229
|
+
### 方法总表
|
|
1230
|
+
|
|
1231
|
+
| 方法 | 参数 | 说明 |
|
|
1232
|
+
| --- | --- | --- |
|
|
1233
|
+
| `upsertVolumeLayer(payload)` | 体渲染配置 | 创建或更新体渲染层。同 `layerId` 会覆盖旧图层。 |
|
|
1234
|
+
| `updateVolumeLayerParameters(payload)` | `{ layerId, parameters }` | 更新体渲染 shader 参数,不重新加载体数据。 |
|
|
1235
|
+
| `showVolumeLayer(payload)` | `{ layerId }` | 显示体渲染层。 |
|
|
1236
|
+
| `hideVolumeLayer(payload)` | `{ layerId }` | 隐藏体渲染层。 |
|
|
1237
|
+
| `removeVolumeLayer(payload)` | `{ layerId }` | 移除体渲染层并释放 Primitive。 |
|
|
1238
|
+
| `flyToVolumeLayer(payload)` | `{ layerId, duration }` | 飞到体渲染层经纬度范围。 |
|
|
1239
|
+
| `getVolumeLayerState(payload)` | `{ layerId }` | 获取图层状态。 |
|
|
1240
|
+
|
|
1241
|
+
### 参数总表
|
|
1242
|
+
|
|
1243
|
+
| 参数 | 是否必填 | 说明 |
|
|
1244
|
+
| --- | --- | --- |
|
|
1245
|
+
| `layerId` / `volumeLayerId` / `id` | 建议必填 | 体渲染图层 id,不传默认 `volume-default`。 |
|
|
1246
|
+
| `data` / `value` / `values` | 必填 | 体数据一维数组,通常按层、行、列展开。 |
|
|
1247
|
+
| `option` | 必填 | 体数据空间范围和网格尺寸。 |
|
|
1248
|
+
| `option.xmin / xmax` | 必填 | 经度最小值和最大值。 |
|
|
1249
|
+
| `option.ymin / ymax` | 必填 | 纬度最小值和最大值。 |
|
|
1250
|
+
| `option.zmin / zmax` | 必填 | 高度最小值和最大值。 |
|
|
1251
|
+
| `option.rows` | 必填 | 纬向网格数量。 |
|
|
1252
|
+
| `option.cols` | 必填 | 经向网格数量。 |
|
|
1253
|
+
| `option.heights` | 必填 | 高度层数量。 |
|
|
1254
|
+
| `parameters.threshold` | 选填 | 采样阈值。 |
|
|
1255
|
+
| `parameters.steps` | 选填 | 光线步进采样次数。 |
|
|
1256
|
+
| `parameters.xCut / yCut / zCut` | 选填 | 三个方向的裁切位置,默认 `-0.5`。 |
|
|
1257
|
+
| `colorRamp` / `colors` / `colorKeys` | 选填 | 自定义色带配置。 |
|
|
1258
|
+
| `geometry` / `dim` | 选填 | 自定义体渲染几何或维度,普通业务通常不需要传。 |
|
|
1259
|
+
| `visible` | 选填 | 初始是否显示,默认显示。 |
|
|
1260
|
+
|
|
1261
|
+
## 三维切片 / 剖面渲染
|
|
1262
|
+
|
|
1263
|
+
三维切片/剖面渲染也是 Cesium 专有能力,直接通过 `BaseGIS` 调用。它把三维网格数据按 X、Y、Z 三个方向切出剖面,适合气象温度、湿度、风场标量、污染物浓度等三维格点数据查看。
|
|
1264
|
+
|
|
1265
|
+
这里的“切片”指三维数据剖面,不是 `ImageLayerController` 里的大图切片。
|
|
1266
|
+
|
|
1267
|
+
### 数据格式
|
|
1268
|
+
|
|
1269
|
+
```js
|
|
1270
|
+
const sectionData = {
|
|
1271
|
+
Bound: [
|
|
1272
|
+
1000, // 0: LayerMax,最高气压层或起始层值。
|
|
1273
|
+
108.68, // 1: LonMin,经度最小值。
|
|
1274
|
+
28.59, // 2: LatMin,纬度最小值。
|
|
1275
|
+
10, // 3: LayerNums,层数。
|
|
1276
|
+
147, // 4: LonNums,经向格点数。
|
|
1277
|
+
198, // 5: LatNums,纬向格点数。
|
|
1278
|
+
900, // 6: DLayer 或 LayerMin 相关值,按数据生成规则提供。
|
|
1279
|
+
16.74, // 7: DLon,经度跨度。
|
|
1280
|
+
16.71, // 8: DLat,纬度跨度。
|
|
1281
|
+
1, // 9: ValueScale,数值缩放。
|
|
1282
|
+
1, // 10: 预留/数据标记。
|
|
1283
|
+
[1000, 925, 850, 700, 600, 500, 400, 300, 200, 100], // 11: LayerList,气压层列表。
|
|
1284
|
+
],
|
|
1285
|
+
// 必填:三维格点值一维数组,长度通常为 LayerNums * LatNums * LonNums。
|
|
1286
|
+
DataAry: valueList,
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
const optionData = {
|
|
1290
|
+
Item: 'TEMP',
|
|
1291
|
+
Values: [-30, -20, -10, 0, 10, 20, 30],
|
|
1292
|
+
Colors: [
|
|
1293
|
+
[30, 80, 180],
|
|
1294
|
+
[50, 160, 220],
|
|
1295
|
+
[120, 220, 180],
|
|
1296
|
+
[250, 230, 120],
|
|
1297
|
+
[240, 150, 80],
|
|
1298
|
+
[220, 80, 60],
|
|
1299
|
+
[160, 30, 30],
|
|
1300
|
+
],
|
|
1301
|
+
}
|
|
1302
|
+
```
|
|
1303
|
+
|
|
1304
|
+
### 加载或更新数据
|
|
1305
|
+
|
|
1306
|
+
同一个 `layerId` 重复调用 `upsertSectionLayer` 就是更新数据。适配层会清理旧切片,再加载新数据。
|
|
1307
|
+
|
|
1308
|
+
```js
|
|
1309
|
+
const result = mapCore.upsertSectionLayer({
|
|
1310
|
+
// 建议必填:切片图层唯一 id。
|
|
1311
|
+
layerId: 'section-demo',
|
|
1312
|
+
|
|
1313
|
+
// 必填:包含 Bound / DataAry 的三维剖面数据。
|
|
1314
|
+
dataInfo: sectionData,
|
|
1315
|
+
|
|
1316
|
+
// 选填:数据类型,传给色标取色逻辑。
|
|
1317
|
+
itemType: optionData.Item,
|
|
1318
|
+
|
|
1319
|
+
// 必填建议:色标配置。
|
|
1320
|
+
colorInfo: {
|
|
1321
|
+
valueAry: optionData.Values,
|
|
1322
|
+
rgbAry: optionData.Colors,
|
|
1323
|
+
},
|
|
1324
|
+
|
|
1325
|
+
// 选填:是否显示坐标轴和刻度。
|
|
1326
|
+
showAxis: false,
|
|
1327
|
+
})
|
|
1328
|
+
|
|
1329
|
+
if (!result.success) {
|
|
1330
|
+
console.warn(result.message)
|
|
1331
|
+
return
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
const state = result.data.state
|
|
1335
|
+
console.log(state.XRange, state.YRange, state.ZRange)
|
|
1336
|
+
```
|
|
1337
|
+
|
|
1338
|
+
### 渲染 X / Y / Z 切片
|
|
1339
|
+
|
|
1340
|
+
```js
|
|
1341
|
+
// X 经度方向切片。
|
|
1342
|
+
mapCore.renderSectionLayer({
|
|
1343
|
+
layerId: 'section-demo',
|
|
1344
|
+
sectionType: 0,
|
|
1345
|
+
value: 116.4,
|
|
1346
|
+
})
|
|
1347
|
+
|
|
1348
|
+
// Y 纬度方向切片。
|
|
1349
|
+
mapCore.renderSectionLayer({
|
|
1350
|
+
layerId: 'section-demo',
|
|
1351
|
+
sectionType: 1,
|
|
1352
|
+
value: 39.9,
|
|
1353
|
+
})
|
|
1354
|
+
|
|
1355
|
+
// Z 高度/气压方向切片。
|
|
1356
|
+
mapCore.renderSectionLayer({
|
|
1357
|
+
layerId: 'section-demo',
|
|
1358
|
+
sectionType: 2,
|
|
1359
|
+
value: 850,
|
|
1360
|
+
})
|
|
1361
|
+
```
|
|
1362
|
+
|
|
1363
|
+
`sectionType` 含义:
|
|
1364
|
+
|
|
1365
|
+
| 值 | 含义 | `value` |
|
|
1366
|
+
| --- | --- | --- |
|
|
1367
|
+
| `0` | 经度方向剖面 | 经度值。 |
|
|
1368
|
+
| `1` | 纬度方向剖面 | 纬度值。 |
|
|
1369
|
+
| `2` | 高度/气压方向剖面 | 气压层或高度层值。 |
|
|
1370
|
+
| `3` | 全量剖面 | 可不传 `value`。 |
|
|
1371
|
+
|
|
1372
|
+
### 显隐、移除和定位
|
|
1373
|
+
|
|
1374
|
+
```js
|
|
1375
|
+
// 隐藏或显示全部切片。
|
|
1376
|
+
mapCore.hideSectionLayer({ layerId: 'section-demo' })
|
|
1377
|
+
mapCore.showSectionLayer({ layerId: 'section-demo' })
|
|
1378
|
+
|
|
1379
|
+
// 只移除 Z 切片,X/Y 不受影响。
|
|
1380
|
+
mapCore.removeSectionLayer({
|
|
1381
|
+
layerId: 'section-demo',
|
|
1382
|
+
sectionType: 2,
|
|
1383
|
+
})
|
|
1384
|
+
|
|
1385
|
+
// 移除整个切片图层。
|
|
1386
|
+
mapCore.removeSectionLayer({ layerId: 'section-demo' })
|
|
1387
|
+
|
|
1388
|
+
// 飞到切片数据范围。
|
|
1389
|
+
mapCore.flyToSectionLayer({ layerId: 'section-demo', duration: 0.8 })
|
|
1390
|
+
```
|
|
1391
|
+
|
|
1392
|
+
### hover 取值
|
|
1393
|
+
|
|
1394
|
+
页面先用 Cesium 拾取得到鼠标所在三维点,再交给 `sampleSectionLayerValue` 计算当前切片上的数值。
|
|
1395
|
+
|
|
1396
|
+
```js
|
|
1397
|
+
const result = mapCore.sampleSectionLayerValue({
|
|
1398
|
+
layerId: 'section-demo',
|
|
1399
|
+
lon: 116.4,
|
|
1400
|
+
lat: 39.9,
|
|
1401
|
+
hpa: 850,
|
|
1402
|
+
// 选填:Z 切片关闭时传 false,避免 hover 命中已隐藏的 Z 切片。
|
|
1403
|
+
showZLayer: true,
|
|
1404
|
+
})
|
|
1405
|
+
|
|
1406
|
+
if (result.success) {
|
|
1407
|
+
console.log(result.data)
|
|
1408
|
+
// { lon, lat, hpa, sectionType, value }
|
|
1409
|
+
}
|
|
1410
|
+
```
|
|
1411
|
+
|
|
1412
|
+
### 方法总表
|
|
1413
|
+
|
|
1414
|
+
| 方法 | 参数 | 说明 |
|
|
1415
|
+
| --- | --- | --- |
|
|
1416
|
+
| `upsertSectionLayer(payload)` | 切片数据与色标配置 | 创建或更新切片图层。同 `layerId` 会覆盖旧图层。 |
|
|
1417
|
+
| `renderSectionLayer(payload)` | `{ layerId, sectionType, value }` | 渲染指定方向切片。 |
|
|
1418
|
+
| `showSectionLayer(payload)` | `{ layerId, sectionType }` | 显示切片。不传 `sectionType` 时显示全部。 |
|
|
1419
|
+
| `hideSectionLayer(payload)` | `{ layerId, sectionType }` | 隐藏切片。不传 `sectionType` 时隐藏全部。 |
|
|
1420
|
+
| `removeSectionLayer(payload)` | `{ layerId, sectionType }` | 移除切片。不传 `sectionType` 时移除整个图层。 |
|
|
1421
|
+
| `flyToSectionLayer(payload)` | `{ layerId, duration }` | 飞到切片数据范围。 |
|
|
1422
|
+
| `getSectionLayerState(payload)` | `{ layerId }` | 获取切片图层状态。 |
|
|
1423
|
+
| `sampleSectionLayerValue(payload)` | `{ layerId, lon, lat, hpa, showZLayer }` | 根据拾取位置计算当前切片数值。 |
|
|
1424
|
+
|
|
1425
|
+
### 参数总表
|
|
1426
|
+
|
|
1427
|
+
| 参数 | 是否必填 | 说明 |
|
|
1428
|
+
| --- | --- | --- |
|
|
1429
|
+
| `layerId` / `sectionLayerId` / `id` | 建议必填 | 切片图层 id,不传默认 `section-default`。 |
|
|
1430
|
+
| `dataInfo` / `data` | 必填 | 三维切片数据,必须包含 `Bound / DataAry`。 |
|
|
1431
|
+
| `dataInfo.Bound` | 必填 | 数据范围、网格数量、层级列表等元信息。 |
|
|
1432
|
+
| `dataInfo.DataAry` | 必填 | 三维格点值一维数组。 |
|
|
1433
|
+
| `itemType` | 选填 | 数据类型,传给色标取色逻辑。 |
|
|
1434
|
+
| `colorInfo.valueAry` | 建议必填 | 色标分级值数组。 |
|
|
1435
|
+
| `colorInfo.rgbAry` | 建议必填 | 色标 RGB 数组。 |
|
|
1436
|
+
| `boxInfo` | 选填 | 自定义剖面盒子范围。不传时根据 `dataInfo` 自动生成。 |
|
|
1437
|
+
| `showAxis` | 选填 | 是否显示坐标轴和刻度。 |
|
|
1438
|
+
| `sectionType` | 渲染、显隐、移除单个切片时必填 | `0` 经度,`1` 纬度,`2` 高度/气压,`3` 全量。 |
|
|
1439
|
+
| `value` / `param` | `sectionType` 为 `0/1/2` 时必填 | 切片位置值。 |
|
|
1440
|
+
| `lon / lat / hpa` | hover 取值必填 | Cesium 拾取得到的经度、纬度、气压高度。 |
|
|
1441
|
+
| `showZLayer` | hover 取值选填 | Z 切片是否参与 hover 命中,默认参与。 |
|
|
1442
|
+
|
|
1443
|
+
## PointLargeLayerController
|
|
1444
|
+
|
|
1445
|
+
用于海量点位渲染。它会尽量把传入的有效点位全部渲染出来,适合站点、设备、告警、监测点等需要保留全部点位并支持点击、高亮、删除、显隐的场景。
|
|
1446
|
+
|
|
1447
|
+
如果业务目标是“地图缩小时按屏幕网格抽稀,只显示代表点”,应使用后文的 `PointDensityController`。
|
|
1448
|
+
|
|
1449
|
+
### Demo 位置
|
|
1450
|
+
|
|
1451
|
+
仓库内已有对应 demo:
|
|
1452
|
+
|
|
1453
|
+
- 路由:`/test-page-5`
|
|
1454
|
+
- 页面:`src/views/test-page-5/index.vue`
|
|
1455
|
+
- 当前 demo 覆盖能力:加载、更新、显隐、高亮、取消高亮、删除点位、清空、销毁、状态读取、视角复位。
|
|
1456
|
+
|
|
1457
|
+
demo 源码内部使用:
|
|
1458
|
+
|
|
1459
|
+
```js
|
|
1460
|
+
import { BaseGIS } from '@/gis'
|
|
1461
|
+
import { PointLargeLayerController } from '@/gis/methods'
|
|
1462
|
+
```
|
|
1463
|
+
|
|
1464
|
+
npm 包外部项目使用:
|
|
1465
|
+
|
|
1466
|
+
```js
|
|
1467
|
+
import { BaseGIS } from '@3clear/basegis'
|
|
1468
|
+
import { PointLargeLayerController } from '@3clear/basegis/methods'
|
|
1469
|
+
```
|
|
1470
|
+
|
|
1471
|
+
### 使用方式一:构造时传入 mapCore
|
|
1472
|
+
|
|
1473
|
+
这是业务页面里最常用的写法。地图初始化完成后创建控制器,再调用 `load` 加载点位。
|
|
1474
|
+
|
|
1475
|
+
```js
|
|
1476
|
+
const mapCore = new BaseGIS({
|
|
1477
|
+
engineType: 'leaflet',
|
|
1478
|
+
containerId: 'map',
|
|
1479
|
+
})
|
|
1480
|
+
|
|
1481
|
+
const initResult = mapCore.init()
|
|
1482
|
+
if (!initResult.success) {
|
|
1483
|
+
console.warn(initResult.message)
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
const pointLayer = new PointLargeLayerController({
|
|
1487
|
+
// 必填:BaseGIS 实例。
|
|
1488
|
+
mapCore,
|
|
1489
|
+
// 建议必填:图层唯一 ID,后续显隐、高亮、删除都基于这个图层。
|
|
1490
|
+
layerId: 'station-large',
|
|
1491
|
+
// 选填:点位唯一值字段,不传默认使用 id。
|
|
1492
|
+
idKey: 'stationCode',
|
|
1493
|
+
|
|
1494
|
+
// 点位数据。也可以使用 data/items 字段;推荐统一使用 points。
|
|
1495
|
+
points,
|
|
1496
|
+
|
|
1497
|
+
// 初始是否显示图层。不传时默认 true。
|
|
1498
|
+
visible: true,
|
|
1499
|
+
|
|
1500
|
+
// 默认普通状态图标。支持图片 URL、base64、data URL。
|
|
1501
|
+
icon: normalPointIcon,
|
|
1502
|
+
|
|
1503
|
+
// 默认高亮状态图标。调用 setHighlight(id) 后使用。
|
|
1504
|
+
highlightIcon: highlightPointIcon,
|
|
1505
|
+
|
|
1506
|
+
// 样式规则读取的字段名。下面 styleRules 里的 gt/default 会基于 value 判断。
|
|
1507
|
+
styleField: 'value',
|
|
1508
|
+
|
|
1509
|
+
// 点位样式规则。从上到下匹配,命中后使用该规则里的 icon/highlightIcon/style 等配置。
|
|
1510
|
+
styleRules: [
|
|
1511
|
+
{
|
|
1512
|
+
// value < 300 时命中
|
|
1513
|
+
lt: 300,
|
|
1514
|
+
icon: lowPointIcon,
|
|
1515
|
+
highlightIcon: highlightPointIcon,
|
|
1516
|
+
},
|
|
1517
|
+
{
|
|
1518
|
+
// value > 780 时命中
|
|
1519
|
+
gt: 780,
|
|
1520
|
+
icon: warningPointIcon,
|
|
1521
|
+
highlightIcon: highlightPointIcon,
|
|
1522
|
+
},
|
|
1523
|
+
{
|
|
1524
|
+
// 300 <= value < 780
|
|
1525
|
+
gte: 300,
|
|
1526
|
+
lt: 780,
|
|
1527
|
+
icon: normalPointIcon,
|
|
1528
|
+
highlightIcon: highlightPointIcon,
|
|
1529
|
+
},
|
|
1530
|
+
{
|
|
1531
|
+
// 兜底规则。没有命中前面规则的点位使用普通图标。
|
|
1532
|
+
default: true,
|
|
1533
|
+
icon: normalPointIcon,
|
|
1534
|
+
highlightIcon: highlightPointIcon,
|
|
1535
|
+
},
|
|
1536
|
+
],
|
|
1537
|
+
|
|
1538
|
+
// 普通图标宽度,单位像素。
|
|
1539
|
+
width: 18,
|
|
1540
|
+
|
|
1541
|
+
// 普通图标高度,单位像素。
|
|
1542
|
+
height: 18,
|
|
1543
|
+
|
|
1544
|
+
// 普通图标缩放比例。
|
|
1545
|
+
scale: 1,
|
|
1546
|
+
|
|
1547
|
+
// 未传 icon 时,可以使用内置圆点图标。下面这些配置用于控制圆点样式。
|
|
1548
|
+
// color: '#19d3a2',
|
|
1549
|
+
// outlineColor: '#ffffff',
|
|
1550
|
+
// outlineWidth: 2,
|
|
1551
|
+
|
|
1552
|
+
// 未传 highlightIcon 时,可以使用内置高亮圆点图标。下面这些配置用于控制高亮圆点样式。
|
|
1553
|
+
// highlightColor: '#ffcf33',
|
|
1554
|
+
// highlightOutlineColor: '#ffffff',
|
|
1555
|
+
// highlightWidth: 20,
|
|
1556
|
+
// highlightHeight: 20,
|
|
1557
|
+
// highlightScale: 1.18,
|
|
1558
|
+
|
|
1559
|
+
// 分帧构建批量大小。点位很多时可以调大或调小,默认 5000。
|
|
1560
|
+
// chunkSize: 10000,
|
|
1561
|
+
|
|
1562
|
+
// Cesium 专用:禁用深度检测距离。需要点位不被地形或模型遮挡时可使用。
|
|
1563
|
+
// disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
1564
|
+
|
|
1565
|
+
// Cesium 专用:按相机距离缩放图标。
|
|
1566
|
+
// 数组含义:[近距离, 近距离缩放, 远距离, 远距离缩放]。
|
|
1567
|
+
// scaleByDistance: [50000, 1, 9000000, 0.34],
|
|
1568
|
+
|
|
1569
|
+
// 点击点位回调。event.data 是原始点位数据。
|
|
1570
|
+
onClick: ({ id, data }) => {`点击点位:${data || id}。`},
|
|
1571
|
+
|
|
1572
|
+
})
|
|
1573
|
+
|
|
1574
|
+
await pointLayer.load({
|
|
1575
|
+
points: [
|
|
1576
|
+
{
|
|
1577
|
+
stationCode: 'A001',
|
|
1578
|
+
name: '站点 A001',
|
|
1579
|
+
longitude: 104,
|
|
1580
|
+
latitude: 35,
|
|
1581
|
+
value: 86,
|
|
1582
|
+
},
|
|
1583
|
+
],
|
|
1584
|
+
})
|
|
1585
|
+
```
|
|
1586
|
+
|
|
1587
|
+
`styleRules` 常用匹配方式:
|
|
1588
|
+
|
|
1589
|
+
| 写法 | 说明 |
|
|
1590
|
+
|---------------------------------------------------| --- |
|
|
1591
|
+
| `{ field: 'aqi', min: 51, max: 100 }` | 指定字段并按区间匹配。 |
|
|
1592
|
+
| `{ gt: 780 }` | 使用 `styleField` 指定的字段做大于判断。 |
|
|
1593
|
+
| `{ gte: 51, lt: 101 }` | 使用 `styleField` 指定的字段做区间判断。 |
|
|
1594
|
+
| `{ values: ['优', '良'] }` | 命中指定值集合。 |
|
|
1595
|
+
| `{ operator: '>', value: 100 }` | 使用操作符匹配,支持 `> / >= / < / <= / == / === / != / !== / in`。 |
|
|
1596
|
+
| `{ when:(point, index, record) { return true } }` | 完全自定义匹配函数。 |
|
|
1597
|
+
| `{ default: true }` | 兜底规则。 |
|
|
1598
|
+
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
### 使用方式:更新数据或样式
|
|
1603
|
+
|
|
1604
|
+
时间轴、实时刷新等场景中,建议复用同一个控制器实例,不要每次刷新都重新 `new PointLargeLayerController()`。
|
|
1605
|
+
|
|
1606
|
+
```js
|
|
1607
|
+
await pointLayer.load({
|
|
1608
|
+
points: firstPoints,
|
|
1609
|
+
icon: normalIcon,
|
|
1610
|
+
})
|
|
1611
|
+
|
|
1612
|
+
// 替换下一批点位。
|
|
1613
|
+
await pointLayer.update({
|
|
1614
|
+
points: nextPoints,
|
|
1615
|
+
})
|
|
1616
|
+
|
|
1617
|
+
// 只更新样式规则。
|
|
1618
|
+
await pointLayer.update({
|
|
1619
|
+
styleField: 'value',
|
|
1620
|
+
styleRules: nextStyleRules,
|
|
1621
|
+
})
|
|
1622
|
+
```
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
### 点位数据格式
|
|
1626
|
+
|
|
1627
|
+
默认支持以下坐标字段:
|
|
1628
|
+
|
|
1629
|
+
- 经度:`longitude / lon / lng / x`
|
|
1630
|
+
- 纬度:`latitude / lat / y`
|
|
1631
|
+
- 高度:`height / altitude / z`
|
|
1632
|
+
- 唯一值:默认 `id`,可通过 `idKey` 指定
|
|
1633
|
+
|
|
1634
|
+
```js
|
|
1635
|
+
const points = [
|
|
1636
|
+
{
|
|
1637
|
+
id: 'large-point-1',
|
|
1638
|
+
name: '点位 1',
|
|
1639
|
+
longitude: 104.1234,
|
|
1640
|
+
latitude: 35.1234,
|
|
1641
|
+
height: 0,
|
|
1642
|
+
value: 820,
|
|
1643
|
+
level: '高',
|
|
1644
|
+
},
|
|
1645
|
+
]
|
|
1646
|
+
```
|
|
1647
|
+
|
|
1648
|
+
### 事件回调
|
|
1649
|
+
|
|
1650
|
+
```js
|
|
1651
|
+
await pointLayer.load({
|
|
1652
|
+
points,
|
|
1653
|
+
onClick(event) {
|
|
1654
|
+
console.log(event.id)
|
|
1655
|
+
console.log(event.data)
|
|
462
1656
|
},
|
|
463
|
-
{
|
|
464
|
-
id
|
|
465
|
-
name: 'TIF 001',
|
|
466
|
-
tifUrl: '/data/grid/001.tif',
|
|
467
|
-
colorize: true,
|
|
1657
|
+
onHover(event) {
|
|
1658
|
+
console.log(event.id)
|
|
468
1659
|
},
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
1660
|
+
onHoverIn(event) {
|
|
1661
|
+
console.log('进入点位', event.id)
|
|
1662
|
+
},
|
|
1663
|
+
onHoverOut(event) {
|
|
1664
|
+
console.log('离开点位', event.id)
|
|
1665
|
+
},
|
|
1666
|
+
tooltipFormatter(event) {
|
|
1667
|
+
return `${event.data.name}:${event.data.value}`
|
|
1668
|
+
},
|
|
1669
|
+
})
|
|
477
1670
|
```
|
|
478
1671
|
|
|
479
|
-
|
|
1672
|
+
事件对象常用字段:
|
|
480
1673
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
1674
|
+
| 字段 | 说明 |
|
|
1675
|
+
| --- | --- |
|
|
1676
|
+
| `layerId` | 图层 ID。 |
|
|
1677
|
+
| `id` | 点位唯一值。 |
|
|
1678
|
+
| `key` | 内部点位 key,通常与 `id` 一致。 |
|
|
1679
|
+
| `index` | 点位在当前数据中的索引。 |
|
|
1680
|
+
| `data` | 原始点位数据。 |
|
|
1681
|
+
| `record` | 标准化后的点位记录。 |
|
|
1682
|
+
| `layer` | 引擎侧海量点图层实例。 |
|
|
1683
|
+
| `movement` | Cesium 鼠标事件对象。 |
|
|
1684
|
+
| `mapEvent` | Leaflet 鼠标事件对象。 |
|
|
1685
|
+
| `picked` / `billboard` / `sprite` | 引擎拾取结果,按当前引擎返回。 |
|
|
487
1686
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
用于 TIF 网格、灰度图网格、外部数值网格。
|
|
1687
|
+
### 常用方法
|
|
491
1688
|
|
|
492
1689
|
```js
|
|
493
|
-
|
|
1690
|
+
// 显示 / 隐藏 / 切换显隐。
|
|
1691
|
+
pointLayer.show()
|
|
1692
|
+
pointLayer.hide()
|
|
1693
|
+
pointLayer.toggle()
|
|
1694
|
+
pointLayer.toggle(true)
|
|
494
1695
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
showProbe: true,
|
|
500
|
-
decimalPlaces: 1,
|
|
501
|
-
})
|
|
1696
|
+
// 高亮 / 取消高亮。
|
|
1697
|
+
pointLayer.setHighlight('A001')
|
|
1698
|
+
pointLayer.highlight('A001')
|
|
1699
|
+
pointLayer.clearHighlight()
|
|
502
1700
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
1701
|
+
// 删除单点 / 批量删除。
|
|
1702
|
+
pointLayer.removePoint('A001')
|
|
1703
|
+
pointLayer.deletePoint('A001')
|
|
1704
|
+
await pointLayer.removePoints(['A001', 'A002'])
|
|
507
1705
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
area: {
|
|
511
|
-
startLon: 73,
|
|
512
|
-
startLat: 18,
|
|
513
|
-
endLon: 135,
|
|
514
|
-
endLat: 54,
|
|
515
|
-
},
|
|
516
|
-
colorize: true,
|
|
517
|
-
})
|
|
1706
|
+
// 清空点位,但保留图层实例。
|
|
1707
|
+
pointLayer.clear()
|
|
518
1708
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
[12.1, 13.4],
|
|
522
|
-
[14.2, 15.6],
|
|
523
|
-
],
|
|
524
|
-
area: {
|
|
525
|
-
startLon: 100,
|
|
526
|
-
startLat: 30,
|
|
527
|
-
endLon: 110,
|
|
528
|
-
endLat: 40,
|
|
529
|
-
},
|
|
530
|
-
})
|
|
1709
|
+
// 从引擎侧重新读取状态。
|
|
1710
|
+
pointLayer.refreshState()
|
|
531
1711
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
1712
|
+
// 销毁图层。
|
|
1713
|
+
pointLayer.destroy()
|
|
1714
|
+
|
|
1715
|
+
// 读取当前状态。
|
|
1716
|
+
pointLayer.getState()
|
|
536
1717
|
```
|
|
537
1718
|
|
|
538
|
-
|
|
1719
|
+
方法说明:
|
|
1720
|
+
|
|
1721
|
+
| 方法 | 说明 |
|
|
1722
|
+
| --- | --- |
|
|
1723
|
+
| `mount(mapCore)` | 挂载 `BaseGIS` 实例。构造时已传 `mapCore/baseGIS` 时通常不需要手动调用。 |
|
|
1724
|
+
| `load(payload, options)` | 加载或覆盖海量点数据。支持 `load(points, options)` 和 `load({ points, ...options })`。 |
|
|
1725
|
+
| `upsert(payload, options)` | `load` 的别名。 |
|
|
1726
|
+
| `update(payload)` | 基于当前配置合并更新。可替换点位,也可只更新样式、图标、显隐参数。 |
|
|
1727
|
+
| `show(payload)` | 显示图层。 |
|
|
1728
|
+
| `hide(payload)` | 隐藏图层。 |
|
|
1729
|
+
| `toggle(visible)` | 切换显隐。不传 `visible` 时按当前状态取反。 |
|
|
1730
|
+
| `setHighlight(id, payload)` | 高亮指定点位。别名:`highlight`、`setHighlighted`。 |
|
|
1731
|
+
| `clearHighlight(payload)` | 清除当前高亮。别名:`clearHighlighted`。 |
|
|
1732
|
+
| `removePoint(id, payload)` | 删除单个点位。别名:`deletePoint`、`removeById`。 |
|
|
1733
|
+
| `removePoints(ids, payload)` | 批量删除点位。别名:`deletePoints`、`removeByIds`。 |
|
|
1734
|
+
| `clear(payload)` | 清空图层点位数据,但保留图层实例。 |
|
|
1735
|
+
| `refreshState(payload)` | 从引擎侧重新读取图层状态。 |
|
|
1736
|
+
| `destroy(payload)` | 销毁图层并释放资源。别名:`removeLayer`。 |
|
|
1737
|
+
| `getState()` | 读取控制器状态。 |
|
|
1738
|
+
|
|
1739
|
+
### 构造和加载参数
|
|
1740
|
+
|
|
1741
|
+
| 参数 | 是否必填 | 默认值 | 说明 |
|
|
1742
|
+
| --- | --- | --- | --- |
|
|
1743
|
+
| `mapCore` / `baseGIS` | 构造时建议必填 | - | `BaseGIS` 实例。也可以后续通过 `mount(mapCore)` 挂载。 |
|
|
1744
|
+
| `layerId` / `pointLargeLayerId` / `largeLayerId` / `id` | 否 | `point-large-default` | 海量点图层 ID。 |
|
|
1745
|
+
| `visible` | 否 | `true` | 初始是否显示。 |
|
|
1746
|
+
| `idKey` | 否 | `id` | 点位唯一值字段。高亮、删除单点依赖该值。 |
|
|
1747
|
+
| `points` / `data` / `items` | 加载时必填其一 | - | 点位数组。 |
|
|
1748
|
+
| `longitudeKeys` | 否 | `['longitude', 'lon', 'lng', 'x']` | 经度字段候选列表。 |
|
|
1749
|
+
| `latitudeKeys` | 否 | `['latitude', 'lat', 'y']` | 纬度字段候选列表。 |
|
|
1750
|
+
| `heightKeys` | 否 | `['height', 'altitude', 'z']` | 高度字段候选列表。 |
|
|
1751
|
+
| `image` / `icon` / `iconUrl` / `imageUrl` | 否 | - | 普通状态图标。未传时使用内置圆点图标。 |
|
|
1752
|
+
| `highlightImage` / `highlightIcon` / `highlightIconUrl` / `highlightImageUrl` | 否 | - | 高亮状态图标。未传时使用高亮圆点图标。 |
|
|
1753
|
+
| `width` / `height` | 否 | `32` | 普通图标尺寸。 |
|
|
1754
|
+
| `scale` | 否 | `1` | 普通图标缩放比例。 |
|
|
1755
|
+
| `color` / `outlineColor` / `outlineWidth` | 否 | `#1e88e5` / `#fff` / `2` | 未传图标时的内置圆点样式。 |
|
|
1756
|
+
| `highlightColor` / `highlightOutlineColor` / `highlightOutlineWidth` | 否 | `#ffcc00` / `#fff` / `3` | 未传高亮图标时的高亮圆点样式。 |
|
|
1757
|
+
| `highlightWidth` / `highlightHeight` / `highlightScale` | 否 | `36` / `36` / `scale * 1.35` | 高亮图标尺寸和缩放。 |
|
|
1758
|
+
| `styleField` / `valueKey` | 否 | `value` | `styleRules` 默认读取的业务值字段。 |
|
|
1759
|
+
| `styleRules` | 否 | `[]` | 点位分级样式规则。 |
|
|
1760
|
+
| `imageCallback` | 否 | - | 自定义返回点位图标。 |
|
|
1761
|
+
| `styleCallback` | 否 | - | 自定义返回普通状态样式。 |
|
|
1762
|
+
| `highlightStyleCallback` | 否 | - | 自定义返回高亮状态样式。 |
|
|
1763
|
+
| `showTooltip` | 否 | `true` | 是否显示内置悬浮提示。 |
|
|
1764
|
+
| `tooltipFormatter` | 否 | - | 自定义悬浮提示内容。 |
|
|
1765
|
+
| `tooltipOffset` | 否 | `[14, 14]` | 悬浮提示偏移。 |
|
|
1766
|
+
| `tooltipClassName` | 否 | - | 悬浮提示 DOM class。 |
|
|
1767
|
+
| `onClick` / `onHover` / `onHoverIn` / `onHoverOut` | 否 | - | 点位事件回调。 |
|
|
1768
|
+
| `chunkSize` | 否 | `5000` | 分帧构建时每批处理数量。 |
|
|
1769
|
+
| `chunkFrameBudget` | 否 | `0` | 分帧构建每帧预算,单位毫秒。 |
|
|
1770
|
+
| `pickRadius` | 否 | `10` | Leaflet / Pixi 模式下的拾取半径。 |
|
|
1771
|
+
| `keepSize` | 否 | `true` | Cesium 下是否尽量保持屏幕像素尺寸。 |
|
|
1772
|
+
| `clampToGround` | 否 | `false` | Cesium 点位是否贴地。 |
|
|
1773
|
+
| `disableDepthTestDistance` | 否 | - | Cesium 深度检测距离。 |
|
|
1774
|
+
| `pixelOffset` / `eyeOffset` | 否 | - | Cesium 图标偏移。 |
|
|
1775
|
+
| `scaleByDistance` | 否 | - | Cesium 按距离缩放。 |
|
|
1776
|
+
| `translucencyByDistance` | 否 | - | Cesium 按距离透明。 |
|
|
1777
|
+
| `distanceDisplayCondition` | 否 | - | Cesium 按距离显示隐藏。 |
|
|
1778
|
+
| `useParticleContainer` | 否 | `false` | Leaflet 下是否使用 Pixi 粒子容器能力。 |
|
|
1779
|
+
| `pixiOptions` | 否 | - | Leaflet / Pixi 渲染参数。 |
|
|
1780
|
+
|
|
1781
|
+
### 状态返回
|
|
1782
|
+
|
|
1783
|
+
```js
|
|
1784
|
+
const state = pointLayer.getState()
|
|
1785
|
+
|
|
1786
|
+
console.log(state)
|
|
1787
|
+
// {
|
|
1788
|
+
// mounted: true,
|
|
1789
|
+
// engineType: 'leaflet',
|
|
1790
|
+
// layerType: 'leaflet-point-large-layer',
|
|
1791
|
+
// visible: true,
|
|
1792
|
+
// layerId: 'station-large',
|
|
1793
|
+
// total: 20000,
|
|
1794
|
+
// renderedCount: 20000,
|
|
1795
|
+
// highlightedId: 'A001',
|
|
1796
|
+
// building: false,
|
|
1797
|
+
// destroyed: false,
|
|
1798
|
+
// payload: {}
|
|
1799
|
+
// }
|
|
1800
|
+
```
|
|
1801
|
+
|
|
1802
|
+
|
|
1803
|
+
## PointDensityController
|
|
1804
|
+
|
|
1805
|
+
用于点位密度抽稀。地图移动、缩放后会按当前视野和屏幕网格重新计算可见点,适合站点、设备、告警、空气质量监测点等高密度点位。
|
|
1806
|
+
|
|
1807
|
+
它和 `PointLargeLayerController` 的区别是:`PointLargeLayerController` 尽量渲染全部有效点;`PointDensityController` 会根据视野、屏幕网格、优先级和最大显示数量筛选一部分点显示。
|
|
1808
|
+
|
|
1809
|
+
### Demo 位置
|
|
539
1810
|
|
|
540
|
-
|
|
1811
|
+
仓库内已有多个点位抽稀 demo:
|
|
1812
|
+
|
|
1813
|
+
- `/test-page-6`:站点 ICON 抽稀,使用 `imageCallback` 按数据绘制站点图标。
|
|
1814
|
+
- `/test-page-8`:空气质量站点抽稀,使用固定 `image` 图标。
|
|
1815
|
+
- `/test-page-13`:空气质量业务页里的城市点位抽稀。
|
|
1816
|
+
|
|
1817
|
+
### 基础用法
|
|
541
1818
|
|
|
542
1819
|
```js
|
|
543
|
-
import {
|
|
1820
|
+
import { PointDensityController } from '@3clear/basegis/methods'
|
|
544
1821
|
|
|
545
|
-
const
|
|
1822
|
+
const density = new PointDensityController({
|
|
1823
|
+
// 必填:BaseGIS 实例。
|
|
546
1824
|
mapCore,
|
|
547
|
-
|
|
1825
|
+
|
|
1826
|
+
// 建议必填:图层唯一 ID。
|
|
1827
|
+
layerId: 'station-density',
|
|
1828
|
+
|
|
1829
|
+
// 点位唯一值字段。不传默认 id。
|
|
548
1830
|
idKey: 'staNum',
|
|
1831
|
+
|
|
1832
|
+
// 抽稀网格大小,单位屏幕像素。同一网格内只保留一个点。
|
|
1833
|
+
gridSize: 150,
|
|
1834
|
+
|
|
1835
|
+
// 最多显示点数。不传默认不限制。
|
|
1836
|
+
maxCount: 500,
|
|
1837
|
+
|
|
1838
|
+
// 同一网格内保留哪个点。字段值越大越优先显示。
|
|
1839
|
+
priorityKey: 'level',
|
|
1840
|
+
|
|
1841
|
+
// 默认图标。
|
|
549
1842
|
image: '/icons/station.png',
|
|
550
|
-
|
|
551
|
-
|
|
1843
|
+
|
|
1844
|
+
// 图标尺寸。
|
|
1845
|
+
width: 28,
|
|
1846
|
+
height: 28,
|
|
1847
|
+
|
|
1848
|
+
// 点击点位回调。第一个参数是原始点位数据。
|
|
552
1849
|
onClick(point) {
|
|
553
|
-
console.log(
|
|
1850
|
+
console.log(point)
|
|
1851
|
+
},
|
|
1852
|
+
|
|
1853
|
+
// 状态变化回调。地图移动、缩放或数据更新后会触发。
|
|
1854
|
+
onStateChange(state) {
|
|
1855
|
+
console.log(state.visibleCount, state.hiddenCount)
|
|
554
1856
|
},
|
|
555
1857
|
})
|
|
556
1858
|
|
|
557
|
-
await
|
|
1859
|
+
await density.load({
|
|
558
1860
|
points: [
|
|
559
|
-
{ staNum: 'A001', longitude: 104, latitude: 35,
|
|
560
|
-
{ staNum: 'A002', longitude:
|
|
1861
|
+
{ staNum: 'A001', longitude: 104, latitude: 35, level: 5 },
|
|
1862
|
+
{ staNum: 'A002', longitude: 104.01, latitude: 35.01, level: 3 },
|
|
561
1863
|
],
|
|
562
1864
|
})
|
|
563
|
-
|
|
564
|
-
largePoints.setHighlight('A001')
|
|
565
|
-
largePoints.clearHighlight()
|
|
566
|
-
largePoints.removePoint('A002')
|
|
567
|
-
largePoints.removePoints(['A001', 'A003'])
|
|
568
|
-
largePoints.hide()
|
|
569
|
-
largePoints.show()
|
|
570
|
-
largePoints.clear()
|
|
571
|
-
largePoints.destroy()
|
|
572
|
-
largePoints.getState()
|
|
573
1865
|
```
|
|
574
1866
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
- 经度:`longitude / lon / lng / x`
|
|
578
|
-
- 纬度:`latitude / lat / y`
|
|
579
|
-
- 高度:`height / altitude / z`
|
|
580
|
-
- 唯一值:默认 `id`,可通过 `idKey` 指定
|
|
581
|
-
|
|
582
|
-
## PointDensityController
|
|
1867
|
+
### 完整配置模板
|
|
583
1868
|
|
|
584
|
-
|
|
1869
|
+
下面的配置接近 `test-page-6` 的写法,字段已加注释。业务中按需保留即可。
|
|
585
1870
|
|
|
586
1871
|
```js
|
|
587
|
-
import { PointDensityController } from '@3clear/basegis/methods'
|
|
588
|
-
|
|
589
1872
|
const density = new PointDensityController({
|
|
1873
|
+
// BaseGIS 实例。控制器只通过 BaseGIS 调用当前引擎能力,不直接依赖 Cesium / Leaflet。
|
|
590
1874
|
mapCore,
|
|
1875
|
+
|
|
1876
|
+
// 图层唯一标识。后续 update/show/hide/clear/destroy 都按该 id 定位图层。
|
|
591
1877
|
layerId: 'station-density',
|
|
1878
|
+
|
|
1879
|
+
// 点位唯一值字段。默认 id;如果点位唯一值在 properties 中,也会尝试读取 properties[idKey]。
|
|
592
1880
|
idKey: 'staNum',
|
|
1881
|
+
|
|
1882
|
+
// 初始是否显示图层。不传默认 true。
|
|
1883
|
+
visible: true,
|
|
1884
|
+
|
|
1885
|
+
// 原始点位数据。也可以不在构造时传,后续 density.load({ points }) 传入。
|
|
1886
|
+
points: stationList,
|
|
1887
|
+
|
|
1888
|
+
// 经度字段候选列表。默认已支持 longitude/lon/lng/x。
|
|
1889
|
+
longitudeKeys: ['longitude', 'lon', 'lng', 'x'],
|
|
1890
|
+
|
|
1891
|
+
// 纬度字段候选列表。默认已支持 latitude/lat/y。
|
|
1892
|
+
latitudeKeys: ['latitude', 'lat', 'y'],
|
|
1893
|
+
|
|
1894
|
+
// 高度字段候选列表。默认已支持 height/altitude/z。
|
|
1895
|
+
heightKeys: ['height', 'altitude', 'z'],
|
|
1896
|
+
|
|
1897
|
+
// 是否开启抽稀。true 时会按屏幕网格去重;false 时只做视野过滤,不做网格碰撞去重。
|
|
1898
|
+
enableThinning: true,
|
|
1899
|
+
|
|
1900
|
+
// 抽稀网格大小,单位屏幕像素。值越大,保留点越少;值越小,保留点越多。
|
|
593
1901
|
gridSize: 150,
|
|
1902
|
+
|
|
1903
|
+
// gridSize 的别名。如果同时传 gridSize 和 pixelRange,以 gridSize 为准。
|
|
1904
|
+
// pixelRange: 150,
|
|
1905
|
+
|
|
1906
|
+
// 最多显示点数量。超过后会按优先级截断。不传默认 Infinity。
|
|
594
1907
|
maxCount: 500,
|
|
1908
|
+
|
|
1909
|
+
// 同一网格内点位优先级字段。字段值越大越优先保留。
|
|
595
1910
|
priorityKey: 'level',
|
|
1911
|
+
|
|
1912
|
+
// 自定义优先级函数。返回值越大越优先保留;传了它后优先级逻辑可完全由业务决定。
|
|
1913
|
+
// priorityCallback(point, markerOrBillboard, index) {
|
|
1914
|
+
// return point.level * 100 + point.value
|
|
1915
|
+
// },
|
|
1916
|
+
|
|
1917
|
+
// 默认图标地址。支持图片 URL、base64、data URL。
|
|
596
1918
|
image: '/icons/station.png',
|
|
1919
|
+
|
|
1920
|
+
// 图标地址别名,和 image 作用一致。
|
|
1921
|
+
// icon: '/icons/station.png',
|
|
1922
|
+
// iconUrl: '/icons/station.png',
|
|
1923
|
+
|
|
1924
|
+
// 按点位动态生成图标。适合空气质量、告警等级等需要每个点图标不同的场景。
|
|
1925
|
+
// 返回值可以是图片地址、base64、data URL。
|
|
1926
|
+
// imageCallback(point, index) {
|
|
1927
|
+
// return createStationIcon(point)
|
|
1928
|
+
// },
|
|
1929
|
+
|
|
1930
|
+
// 图标宽度,单位像素。
|
|
597
1931
|
width: 28,
|
|
1932
|
+
|
|
1933
|
+
// 图标高度,单位像素。
|
|
598
1934
|
height: 28,
|
|
1935
|
+
|
|
1936
|
+
// 地图移动、缩放后重新计算抽稀的节流时间,单位毫秒。
|
|
1937
|
+
throttleTime: 120,
|
|
1938
|
+
|
|
1939
|
+
// Cesium 专用:视野过滤缓冲,单位屏幕像素。
|
|
1940
|
+
// 值越大,视野边缘附近的点越不容易在移动时频繁出现/消失。
|
|
1941
|
+
viewportBuffer: 100,
|
|
1942
|
+
|
|
1943
|
+
// Cesium 专用:3D 场景下是否剔除地球背面的点。
|
|
1944
|
+
cullByGlobe: true,
|
|
1945
|
+
|
|
1946
|
+
// Cesium 专用:Billboard 是否贴地。
|
|
1947
|
+
clampToGround: false,
|
|
1948
|
+
|
|
1949
|
+
// Cesium 专用:Billboard 缩放比例。
|
|
1950
|
+
scale: 1,
|
|
1951
|
+
|
|
1952
|
+
// Cesium 专用:禁用深度检测距离。
|
|
1953
|
+
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
1954
|
+
|
|
1955
|
+
// Cesium 专用:平滑更新,减少刷新抽稀结果时的突兀感。
|
|
1956
|
+
smoothUpdate: true,
|
|
1957
|
+
smoothUpdateFrames: 2,
|
|
1958
|
+
|
|
1959
|
+
// Leaflet 专用:视野 bounds 扩展比例。
|
|
1960
|
+
// 例如 0.1 表示在当前视野基础上向外扩展 10% 后再过滤点位。
|
|
1961
|
+
boundsBufferRatio: 0,
|
|
1962
|
+
|
|
1963
|
+
// Leaflet 专用:Marker 层级偏移。
|
|
1964
|
+
zIndexOffset: 0,
|
|
1965
|
+
|
|
1966
|
+
// 点位点击回调。第一个参数是原始点位数据。
|
|
599
1967
|
onClick(point) {
|
|
600
1968
|
console.log(point)
|
|
601
1969
|
},
|
|
1970
|
+
|
|
1971
|
+
// 状态变化回调。每次抽稀刷新、显隐、清空后会尽量触发。
|
|
602
1972
|
onStateChange(state) {
|
|
603
1973
|
console.log(state.visibleCount, state.hiddenCount)
|
|
604
1974
|
},
|
|
605
1975
|
})
|
|
1976
|
+
```
|
|
606
1977
|
|
|
1978
|
+
### 点位数据格式
|
|
1979
|
+
|
|
1980
|
+
`load` 支持直接传数组,也支持传对象。对象中点位字段支持 `points / data / items`,推荐统一使用 `points`。
|
|
1981
|
+
|
|
1982
|
+
```js
|
|
607
1983
|
await density.load({
|
|
608
1984
|
points: [
|
|
609
1985
|
{ staNum: 'A001', longitude: 104, latitude: 35, level: 5 },
|
|
610
1986
|
{ staNum: 'A002', longitude: 104.01, latitude: 35.01, level: 3 },
|
|
611
1987
|
],
|
|
612
1988
|
})
|
|
1989
|
+
```
|
|
1990
|
+
|
|
1991
|
+
也可以写成:
|
|
1992
|
+
|
|
1993
|
+
```js
|
|
1994
|
+
await density.load([
|
|
1995
|
+
{ id: 'A001', lon: 104, lat: 35, value: 86 },
|
|
1996
|
+
{ id: 'A002', lon: 104.01, lat: 35.01, value: 120 },
|
|
1997
|
+
])
|
|
1998
|
+
|
|
1999
|
+
await density.load({
|
|
2000
|
+
data: [
|
|
2001
|
+
{ id: 'A001', x: 104, y: 35 },
|
|
2002
|
+
],
|
|
2003
|
+
})
|
|
2004
|
+
```
|
|
2005
|
+
|
|
2006
|
+
默认坐标字段:
|
|
2007
|
+
|
|
2008
|
+
- 经度:`longitude / lon / lng / x`
|
|
2009
|
+
- 纬度:`latitude / lat / y`
|
|
2010
|
+
- 高度:`height / altitude / z`
|
|
2011
|
+
- 唯一值:默认 `id`,可通过 `idKey` 指定。
|
|
2012
|
+
|
|
2013
|
+
### 抽稀规则
|
|
2014
|
+
|
|
2015
|
+
核心规则:
|
|
2016
|
+
|
|
2017
|
+
1. 先按当前地图视野过滤点位。
|
|
2018
|
+
2. `enableThinning: true` 时,再按屏幕像素网格抽稀。
|
|
2019
|
+
3. 同一网格内默认保留优先级更高的点。
|
|
2020
|
+
4. 如果设置了 `maxCount`,最终显示数量不会超过该值。
|
|
2021
|
+
|
|
2022
|
+
优先级规则:
|
|
2023
|
+
|
|
2024
|
+
```js
|
|
2025
|
+
const density = new PointDensityController({
|
|
2026
|
+
mapCore,
|
|
2027
|
+
layerId: 'station-density',
|
|
2028
|
+
points,
|
|
2029
|
+
gridSize: 120,
|
|
2030
|
+
|
|
2031
|
+
// 简单写法:按字段值排序,值越大越优先显示。
|
|
2032
|
+
priorityKey: 'value',
|
|
2033
|
+
})
|
|
2034
|
+
```
|
|
2035
|
+
|
|
2036
|
+
复杂优先级可以用 `priorityCallback`:
|
|
2037
|
+
|
|
2038
|
+
```js
|
|
2039
|
+
const density = new PointDensityController({
|
|
2040
|
+
mapCore,
|
|
2041
|
+
layerId: 'station-density',
|
|
2042
|
+
points,
|
|
2043
|
+
gridSize: 120,
|
|
2044
|
+
priorityCallback(point, markerOrBillboard, index) {
|
|
2045
|
+
const alarmWeight = point.alarm ? 10000 : 0
|
|
2046
|
+
return alarmWeight + Number(point.value || 0) - index * 0.001
|
|
2047
|
+
},
|
|
2048
|
+
})
|
|
2049
|
+
```
|
|
2050
|
+
|
|
2051
|
+
### 更新配置
|
|
613
2052
|
|
|
2053
|
+
地图上已经有图层后,可以通过 `update` 或 `setConfig` 更新数据或抽稀参数。
|
|
2054
|
+
|
|
2055
|
+
```js
|
|
2056
|
+
// 更新抽稀网格。
|
|
614
2057
|
density.update({ gridSize: 120 })
|
|
2058
|
+
|
|
2059
|
+
// 关闭抽稀,只做视野过滤。
|
|
2060
|
+
density.update({ enableThinning: false })
|
|
2061
|
+
|
|
2062
|
+
// 替换点位数据。
|
|
2063
|
+
density.update({
|
|
2064
|
+
points: nextPoints,
|
|
2065
|
+
})
|
|
2066
|
+
|
|
2067
|
+
// setConfig 是 update 的别名,更适合只表达“改配置”的场景。
|
|
2068
|
+
density.setConfig({
|
|
2069
|
+
gridSize: 180,
|
|
2070
|
+
maxCount: 300,
|
|
2071
|
+
})
|
|
2072
|
+
```
|
|
2073
|
+
|
|
2074
|
+
### 显隐、清空和销毁
|
|
2075
|
+
|
|
2076
|
+
```js
|
|
615
2077
|
density.hide()
|
|
616
2078
|
density.show()
|
|
617
2079
|
density.toggle()
|
|
2080
|
+
density.toggle(true)
|
|
618
2081
|
density.refreshState()
|
|
619
2082
|
density.clear()
|
|
620
2083
|
density.destroy()
|
|
621
2084
|
```
|
|
622
2085
|
|
|
623
|
-
|
|
2086
|
+
方法说明:
|
|
2087
|
+
|
|
2088
|
+
| 方法 | 说明 |
|
|
2089
|
+
| --- | --- |
|
|
2090
|
+
| `mount(mapCore)` | 挂载 `BaseGIS` 实例。构造时已传 `mapCore/baseGIS` 时通常不需要手动调用。 |
|
|
2091
|
+
| `load(payload, options)` | 加载或覆盖抽稀点位数据。支持 `load(points, options)` 和 `load({ points, ...options })`。 |
|
|
2092
|
+
| `upsert(payload, options)` | `load` 的别名。 |
|
|
2093
|
+
| `update(payload)` | 合并当前配置后重新加载。可更新点位、抽稀参数、图标、事件等。 |
|
|
2094
|
+
| `setConfig(payload)` | `update` 的别名。适合只更新抽稀参数。 |
|
|
2095
|
+
| `show(payload)` | 显示图层。 |
|
|
2096
|
+
| `hide(payload)` | 隐藏图层。 |
|
|
2097
|
+
| `toggle(visible)` | 切换显隐。不传 `visible` 时按当前状态取反。 |
|
|
2098
|
+
| `clear(payload)` | 清空图层点位数据,但保留图层实例。 |
|
|
2099
|
+
| `refreshState(payload)` | 从引擎侧重新读取图层状态。 |
|
|
2100
|
+
| `destroy(payload)` | 销毁图层并释放资源。别名:`removeLayer`。 |
|
|
2101
|
+
| `getState()` | 读取控制器状态。 |
|
|
2102
|
+
|
|
2103
|
+
### 参数总表
|
|
2104
|
+
|
|
2105
|
+
| 参数 | 是否必填 | 默认值 | 说明 |
|
|
2106
|
+
| --- | --- | --- | --- |
|
|
2107
|
+
| `mapCore` / `baseGIS` | 构造时建议必填 | - | `BaseGIS` 实例。也可以后续调用 `mount(mapCore)`。 |
|
|
2108
|
+
| `layerId` / `pointDensityLayerId` / `densityLayerId` / `id` | 否 | `point-density-default` | 点位抽稀图层 ID。 |
|
|
2109
|
+
| `points` / `data` / `items` | 加载时必填其一 | - | 点位数据数组,也支持 GeoJSON FeatureCollection。 |
|
|
2110
|
+
| `idKey` | 否 | `id` | 点位唯一标识字段。 |
|
|
2111
|
+
| `longitudeKeys` | 否 | `['longitude', 'lon', 'lng', 'x']` | 经度字段候选名。 |
|
|
2112
|
+
| `latitudeKeys` | 否 | `['latitude', 'lat', 'y']` | 纬度字段候选名。 |
|
|
2113
|
+
| `heightKeys` | 否 | `['height', 'altitude', 'z']` | 高度字段候选名。 |
|
|
2114
|
+
| `visible` | 否 | `true` | 初始是否显示图层。 |
|
|
2115
|
+
| `enableThinning` | 否 | `true` | 是否开启抽稀;关闭后只做视野过滤。 |
|
|
2116
|
+
| `gridSize` | 否 | `150` | 抽稀网格大小,单位屏幕像素。 |
|
|
2117
|
+
| `pixelRange` | 否 | `150` | `gridSize` 的别名。 |
|
|
2118
|
+
| `maxCount` | 否 | `Infinity` | 单次最多显示的点数量。 |
|
|
2119
|
+
| `priorityKey` | 否 | - | 同一网格内点位优先级字段,值越大越优先显示。 |
|
|
2120
|
+
| `priorityCallback` | 否 | - | 自定义优先级函数,返回值越大越优先显示。 |
|
|
2121
|
+
| `image` / `icon` / `iconUrl` | 否 | - | 默认图标地址。 |
|
|
2122
|
+
| `imageCallback` | 否 | - | 图标生成函数,适合每个点图标不同的场景。 |
|
|
2123
|
+
| `width` | 否 | `32` | 图标宽度,单位像素。 |
|
|
2124
|
+
| `height` | 否 | `32` | 图标高度,单位像素。 |
|
|
2125
|
+
| `throttleTime` | 否 | `120` | 地图移动、缩放后刷新抽稀的节流时间,单位毫秒。 |
|
|
2126
|
+
| `onClick` | 否 | - | 点位点击回调。第一个参数为原始点位数据。 |
|
|
2127
|
+
| `onStateChange` | 否 | - | 图层状态变化回调。 |
|
|
2128
|
+
| `viewportBuffer` | 否 | `100` | Cesium 专用:视野过滤缓冲,单位屏幕像素。 |
|
|
2129
|
+
| `cullByGlobe` | 否 | `true` | Cesium 专用:3D 场景下是否剔除地球背面点。 |
|
|
2130
|
+
| `clampToGround` | 否 | `false` | Cesium 专用:Billboard 是否贴地。 |
|
|
2131
|
+
| `scale` | 否 | `1` | Cesium 专用:Billboard 缩放比例。 |
|
|
2132
|
+
| `disableDepthTestDistance` | 否 | `Infinity` | Cesium 专用:禁用深度检测距离。 |
|
|
2133
|
+
| `smoothUpdate` | 否 | `true` | Cesium 专用:是否平滑更新抽稀结果。 |
|
|
2134
|
+
| `smoothUpdateFrames` | 否 | `2` | Cesium 专用:平滑更新保留旧集合的帧数。 |
|
|
2135
|
+
| `boundsBufferRatio` | 否 | `0` | Leaflet 专用:视野 bounds 扩展比例。 |
|
|
2136
|
+
| `zIndexOffset` | 否 | `0` | Leaflet 专用:Marker 层级偏移。 |
|
|
2137
|
+
|
|
2138
|
+
### 状态返回
|
|
2139
|
+
|
|
2140
|
+
`getState()` 和 `onStateChange(state)` 返回的状态结构基本一致:
|
|
624
2141
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
2142
|
+
```js
|
|
2143
|
+
const state = density.getState()
|
|
2144
|
+
|
|
2145
|
+
console.log(state)
|
|
2146
|
+
// {
|
|
2147
|
+
// mounted: true,
|
|
2148
|
+
// engineType: 'cesium',
|
|
2149
|
+
// layerType: 'cesium-point-density-layer',
|
|
2150
|
+
// visible: true,
|
|
2151
|
+
// layerId: 'station-density',
|
|
2152
|
+
// sourceCount: 10000,
|
|
2153
|
+
// visibleCount: 420,
|
|
2154
|
+
// hiddenCount: 9580,
|
|
2155
|
+
// gridCount: 420,
|
|
2156
|
+
// gridSize: 150,
|
|
2157
|
+
// destroyed: false,
|
|
2158
|
+
// payload: {}
|
|
2159
|
+
// }
|
|
2160
|
+
```
|
|
632
2161
|
|
|
633
2162
|
## ContourLayerController
|
|
634
2163
|
|
|
@@ -676,40 +2205,69 @@ contour.destroy()
|
|
|
676
2205
|
|
|
677
2206
|
数据别名支持 `contours / isolines / isoline / lines / data / items`。
|
|
678
2207
|
|
|
679
|
-
|
|
2208
|
+
[//]: # ()
|
|
2209
|
+
[//]: # (## PressureContourLayer)
|
|
680
2210
|
|
|
681
|
-
|
|
2211
|
+
[//]: # ()
|
|
2212
|
+
[//]: # (用于等压线和高低压中心标注。`buildPressureRenderData()` 可把 Windy 风格的 `press.json` 数据整理成渲染结构,`createPressureDataResolver()` 提供简单缓存。)
|
|
682
2213
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
PressureContourLayer,
|
|
686
|
-
createPressureDataResolver,
|
|
687
|
-
} from '@3clear/basegis/methods'
|
|
2214
|
+
[//]: # ()
|
|
2215
|
+
[//]: # (```js)
|
|
688
2216
|
|
|
689
|
-
|
|
690
|
-
default: pressJson,
|
|
691
|
-
next: pressJson2,
|
|
692
|
-
})
|
|
2217
|
+
[//]: # (import {)
|
|
693
2218
|
|
|
694
|
-
|
|
695
|
-
mapCore,
|
|
696
|
-
layerId: 'pressure',
|
|
697
|
-
color: 'rgba(255,255,255,0.82)',
|
|
698
|
-
width: 1.15,
|
|
699
|
-
smoothFactor: 0.2,
|
|
700
|
-
// Cesium 场景下用于定位容器尺寸,Leaflet 场景也可以传同一个地图容器 id。
|
|
701
|
-
mapContainerId: 'map',
|
|
702
|
-
// 标注层通过该函数读取当前数据,便于地图缩放后重建标签。
|
|
703
|
-
getData: () => resolvePressureData('default'),
|
|
704
|
-
isAnnotationVisible: () => true,
|
|
705
|
-
})
|
|
2219
|
+
[//]: # ( PressureContourLayer,)
|
|
706
2220
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
2221
|
+
[//]: # ( createPressureDataResolver,)
|
|
2222
|
+
|
|
2223
|
+
[//]: # (} from '@3clear/basegis/methods')
|
|
2224
|
+
|
|
2225
|
+
[//]: # ()
|
|
2226
|
+
[//]: # (const resolvePressureData = createPressureDataResolver({)
|
|
2227
|
+
|
|
2228
|
+
[//]: # ( default: pressJson,)
|
|
2229
|
+
|
|
2230
|
+
[//]: # ( next: pressJson2,)
|
|
2231
|
+
|
|
2232
|
+
[//]: # (}))
|
|
2233
|
+
|
|
2234
|
+
[//]: # ()
|
|
2235
|
+
[//]: # (const pressureLayer = new PressureContourLayer({)
|
|
2236
|
+
|
|
2237
|
+
[//]: # ( mapCore,)
|
|
2238
|
+
|
|
2239
|
+
[//]: # ( layerId: 'pressure',)
|
|
2240
|
+
|
|
2241
|
+
[//]: # ( color: 'rgba(255,255,255,0.82)',)
|
|
2242
|
+
|
|
2243
|
+
[//]: # ( width: 1.15,)
|
|
2244
|
+
|
|
2245
|
+
[//]: # ( smoothFactor: 0.2,)
|
|
2246
|
+
|
|
2247
|
+
[//]: # ( // Cesium 场景下用于定位容器尺寸,Leaflet 场景也可以传同一个地图容器 id。)
|
|
2248
|
+
|
|
2249
|
+
[//]: # ( mapContainerId: 'map',)
|
|
2250
|
+
|
|
2251
|
+
[//]: # ( // 标注层通过该函数读取当前数据,便于地图缩放后重建标签。)
|
|
2252
|
+
|
|
2253
|
+
[//]: # ( getData: () => resolvePressureData('default'),)
|
|
2254
|
+
|
|
2255
|
+
[//]: # ( isAnnotationVisible: () => true,)
|
|
2256
|
+
|
|
2257
|
+
[//]: # (}))
|
|
2258
|
+
|
|
2259
|
+
[//]: # ()
|
|
2260
|
+
[//]: # (pressureLayer.mount())
|
|
2261
|
+
|
|
2262
|
+
[//]: # (await pressureLayer.load(resolvePressureData('default')))
|
|
2263
|
+
|
|
2264
|
+
[//]: # (await pressureLayer.update(resolvePressureData('next')))
|
|
2265
|
+
|
|
2266
|
+
[//]: # (pressureLayer.hide())
|
|
2267
|
+
|
|
2268
|
+
[//]: # (pressureLayer.destroy())
|
|
2269
|
+
|
|
2270
|
+
[//]: # (```)
|
|
713
2271
|
|
|
714
2272
|
说明:
|
|
715
2273
|
|
|
@@ -749,58 +2307,138 @@ wind.clearWindFields()
|
|
|
749
2307
|
wind.getState()
|
|
750
2308
|
```
|
|
751
2309
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
控制器适合页面长期维护状态。如果只是一次调用,也可以直接用 `BaseGIS` 方法。
|
|
2310
|
+
### 构造参数
|
|
755
2311
|
|
|
756
2312
|
```js
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
startLat: 18,
|
|
763
|
-
endLon: 135,
|
|
764
|
-
endLat: 54,
|
|
765
|
-
},
|
|
766
|
-
})
|
|
767
|
-
mapCore.hideImageLayer({ layerId: 'image-layer' })
|
|
768
|
-
mapCore.showImageLayer({ layerId: 'image-layer' })
|
|
769
|
-
mapCore.removeImageLayer({ layerId: 'image-layer' })
|
|
2313
|
+
const wind = new WindFieldMethods({ mapCore })
|
|
2314
|
+
// 等价写法:
|
|
2315
|
+
// const wind = new WindFieldMethods({ baseGIS: mapCore })
|
|
2316
|
+
// const wind = new WindFieldMethods(mapCore)
|
|
2317
|
+
```
|
|
770
2318
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
mapCore.removeGridLayer({ layerId: 'grid-layer' })
|
|
2319
|
+
| 参数 | 类型 | 是否必填 | 说明 |
|
|
2320
|
+
| --- | --- | --- | --- |
|
|
2321
|
+
| `mapCore` | `BaseGIS` | 是 | `BaseGIS` 实例。构造时传入会自动 `mount`。 |
|
|
2322
|
+
| `baseGIS` | `BaseGIS` | 是 | `mapCore` 的别名。 |
|
|
776
2323
|
|
|
777
|
-
|
|
778
|
-
layerId: 'large-points',
|
|
779
|
-
points: [{ id: '1', longitude: 104, latitude: 35 }],
|
|
780
|
-
})
|
|
781
|
-
mapCore.setPointLargeHighlight({ layerId: 'large-points', pointId: '1' })
|
|
782
|
-
mapCore.clearPointLargeHighlight({ layerId: 'large-points' })
|
|
783
|
-
mapCore.removePointLargePoint({ layerId: 'large-points', pointId: '1' })
|
|
784
|
-
mapCore.clearPointLargeLayer({ layerId: 'large-points' })
|
|
785
|
-
mapCore.removePointLargeLayer({ layerId: 'large-points' })
|
|
2324
|
+
如果构造时没有传 `mapCore / baseGIS`,可以后续调用 `wind.mount(mapCore)`。目标实例必须提供 `getMapInstance / getMapContainer / projectToContainerPoint / getViewBounds / onViewChange` 等 `BaseGIS` 公共方法。
|
|
786
2325
|
|
|
787
|
-
|
|
788
|
-
layerId: 'density-points',
|
|
789
|
-
points: [{ id: '1', longitude: 104, latitude: 35 }],
|
|
790
|
-
gridSize: 150,
|
|
791
|
-
})
|
|
792
|
-
mapCore.getPointDensityLayerState({ layerId: 'density-points' })
|
|
793
|
-
mapCore.removePointDensityLayer({ layerId: 'density-points' })
|
|
2326
|
+
### 风场数据格式
|
|
794
2327
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
2328
|
+
`addWindField` 的 `data` 和 `updateWindField` 的 `data` 使用项目约定的 `Bound / DataAry` 结构:
|
|
2329
|
+
|
|
2330
|
+
```js
|
|
2331
|
+
const windData = {
|
|
2332
|
+
// [经度最小值, 纬度最小值, 经向网格数, 纬向网格数, 经度跨度, 纬度跨度, 数值缩放]
|
|
2333
|
+
Bound: [70, 15, 121, 81, 60, 40, 10],
|
|
2334
|
+
// 从左下角开始,按行平铺;每个格点两个值:[u, v]
|
|
2335
|
+
DataAry: [
|
|
2336
|
+
// u0, v0, u1, v1, ...
|
|
2337
|
+
],
|
|
2338
|
+
}
|
|
802
2339
|
```
|
|
803
2340
|
|
|
2341
|
+
| 字段 | 类型 | 是否必填 | 说明 |
|
|
2342
|
+
| --- | --- | --- | --- |
|
|
2343
|
+
| `Bound[0]` | `number` | 是 | `lonMin`,风场网格西边界经度。 |
|
|
2344
|
+
| `Bound[1]` | `number` | 是 | `latMin`,风场网格南边界纬度。 |
|
|
2345
|
+
| `Bound[2]` | `number` | 是 | `lonCount`,经向格点数量,必须大于等于 `2`。 |
|
|
2346
|
+
| `Bound[3]` | `number` | 是 | `latCount`,纬向格点数量,必须大于等于 `2`。 |
|
|
2347
|
+
| `Bound[4]` | `number` | 是 | `lonSpan`,经度跨度,东边界为 `lonMin + lonSpan`。 |
|
|
2348
|
+
| `Bound[5]` | `number` | 是 | `latSpan`,纬度跨度,北边界为 `latMin + latSpan`。 |
|
|
2349
|
+
| `Bound[6]` | `number` | 否 | `valueScale`,数值缩放系数,默认 `1`;实际风速分量为 `DataAry / valueScale`。 |
|
|
2350
|
+
| `DataAry` | `number[]` | 是 | 风矢量数组,长度必须等于 `lonCount * latCount * 2`。每个格点依次存 `u / v` 两个分量。 |
|
|
2351
|
+
|
|
2352
|
+
数据按“左下角开始、从南到北逐行、每行从西到东”的顺序平铺。渲染时会对 `u / v` 做双线性插值,粒子速度使用 `Math.hypot(u, v)`。
|
|
2353
|
+
|
|
2354
|
+
### addWindField / updateWindField 参数
|
|
2355
|
+
|
|
2356
|
+
`addWindField(payload)` 用于新增风场;如果同 id 已存在,会先移除旧风场再创建。`updateWindField(payload)` 用于更新已有风场的参数或数据。
|
|
2357
|
+
|
|
2358
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
2359
|
+
| --- | --- | --- | --- |
|
|
2360
|
+
| `id` | `string` | `wind-field-default` | 风场 id。后续 start/stop/show/hide/remove 都按该 id 查找。 |
|
|
2361
|
+
| `layerId` | `string` | `wind-field-default` | `id` 的别名。`id` 优先级更高。 |
|
|
2362
|
+
| `data` | `object` | - | 风场数据。`addWindField` 必填;`updateWindField` 可选,传入时会替换旧数据。 |
|
|
2363
|
+
| `windData` | `object` | - | `data` 的别名。 |
|
|
2364
|
+
| `options` | `object` | `{}` | 渲染参数集合。会和 payload 顶层其它参数合并,顶层参数优先级低于 `options` 内同名参数。 |
|
|
2365
|
+
| `visible` | `boolean` | `true` | 初始是否显示 Canvas。隐藏后仍保留图层实例。 |
|
|
2366
|
+
| `running` | `boolean` | `true` | 初始是否播放粒子动画。 |
|
|
2367
|
+
| `zIndex` | `number` | `30` | 风场 Canvas 层级。速度底图使用该值,粒子层使用 `zIndex + 1`。 |
|
|
2368
|
+
| `height` | `number` | `0` | 投影时使用的高度,主要影响 Cesium 场景。 |
|
|
2369
|
+
| `devicePixelRatio` | `number` | `window.devicePixelRatio` | Canvas 渲染倍率,内部会限制在 `1 ~ 2`。 |
|
|
2370
|
+
|
|
2371
|
+
### 粒子动画参数
|
|
2372
|
+
|
|
2373
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
2374
|
+
| --- | --- | --- | --- |
|
|
2375
|
+
| `particleCount` | `number` | `1400` | 粒子总数。数值越大越密,渲染开销越高。 |
|
|
2376
|
+
| `maxFrameParticles` | `number` | `1200` | 单帧最多推进和绘制的粒子数。 |
|
|
2377
|
+
| `frameParticleLimit` | `number` | `1200` | `maxFrameParticles` 的别名。 |
|
|
2378
|
+
| `sceneModeMaxFrameParticles` | `number` | `0` | 场景模式相关帧粒子上限预留参数。当前未作为主路径使用。 |
|
|
2379
|
+
| `maxAge` | `number` | `58` | 粒子最大生命周期,超过后重新随机出生。 |
|
|
2380
|
+
| `frameRate` | `number` | `30` | 粒子动画目标帧率,内部限制在 `1 ~ 60`。 |
|
|
2381
|
+
| `velocityScale` | `number` | `900` | 风速到粒子位移的缩放系数。数值越大粒子移动越快。 |
|
|
2382
|
+
| `lineWidth` | `number` | `0.85` | 粒子轨迹基础线宽。 |
|
|
2383
|
+
| `color` | `string` | `rgba(230, 248, 255, 0.52)` | 粒子单色兜底颜色。传了 `particleColorScale` 时优先按风速分级着色。 |
|
|
2384
|
+
| `particleOpacity` | `number` | `0.58` | 粒子轨迹透明度。 |
|
|
2385
|
+
| `fadeOpacity` | `number` | `0.86` | 拖尾淡出强度,越接近 `1` 轨迹残留越长。 |
|
|
2386
|
+
| `blendMode` | `string` | `lighter` | Canvas 合成模式,例如 `source-over`、`lighter`。 |
|
|
2387
|
+
| `particleColorScale` | `Array` | 内置色标 | 粒子颜色分级。支持 `{ value, color }`、`{ speed, color }`、`[value, color]`。 |
|
|
2388
|
+
|
|
2389
|
+
### 速度底图参数
|
|
2390
|
+
|
|
2391
|
+
风场默认会额外绘制一层速度底图,用于表达风速强弱;只想显示粒子时可以关闭。
|
|
2392
|
+
|
|
2393
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
2394
|
+
| --- | --- | --- | --- |
|
|
2395
|
+
| `velocityOverlay` | `boolean` | `true` | 是否绘制速度底图。 |
|
|
2396
|
+
| `velocityOverlayOpacity` | `number` | `0.22` | 速度底图透明度。 |
|
|
2397
|
+
| `velocityOverlayCellSize` | `number` | `54` | 速度底图采样网格像素大小。 |
|
|
2398
|
+
| `velocityOverlayEdgeFade` | `number` | `0.12` | 速度底图边缘淡出比例。 |
|
|
2399
|
+
| `colorScale` | `Array` | 内置色标 | 速度底图颜色分级。支持 `{ value, color }`、`{ speed, color }`、`[value, color]`。 |
|
|
2400
|
+
|
|
2401
|
+
`color` 可以写成 `#4ab3ff`、`rgb(80, 180, 255)`、`rgba(80, 180, 255, 0.8)` 或 `[80, 180, 255]`。
|
|
2402
|
+
|
|
2403
|
+
### 交互与投影参数
|
|
2404
|
+
|
|
2405
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
2406
|
+
| --- | --- | --- | --- |
|
|
2407
|
+
| `interactionResumeDelay` | `number` | `80` | 地图交互结束后恢复动画的延迟,单位毫秒。交互过程中会暂停粒子绘制。 |
|
|
2408
|
+
| `projectionGrid` | `boolean` | `true` | 2D / 2.5D 场景是否启用投影网格缓存。 |
|
|
2409
|
+
| `projectionGridCols` | `number` | `32` | 投影网格列数,内部限制在 `8 ~ 96`。 |
|
|
2410
|
+
| `projectionGridRows` | `number` | `20` | 投影网格行数,内部限制在 `6 ~ 64`。 |
|
|
2411
|
+
| `reset` | `boolean` | `false` | `updateWindField` 时传 `true` 会强制重置粒子。 |
|
|
2412
|
+
|
|
2413
|
+
`container / project / getViewBounds / getSceneMode` 由 `WindFieldMethods` 根据 `BaseGIS` 自动注入,业务侧不要传这些字段作为主路径。
|
|
2414
|
+
|
|
2415
|
+
### 控制方法
|
|
2416
|
+
|
|
2417
|
+
| 方法 | 参数 | 说明 |
|
|
2418
|
+
| --- | --- | --- |
|
|
2419
|
+
| `mount(mapCore)` | `BaseGIS` 实例 | 后挂载 `BaseGIS`。 |
|
|
2420
|
+
| `addWindField(payload)` | 风场数据与渲染参数 | 新增风场。`data / windData` 必填。 |
|
|
2421
|
+
| `updateWindField(payload)` | `{ id, ...options }` | 更新已有风场。可只更新样式、粒子参数,也可传 `data / windData` 替换数据。 |
|
|
2422
|
+
| `startWindField(idOrPayload)` | `string` 或 `{ id / layerId }` | 启动粒子动画。 |
|
|
2423
|
+
| `stopWindField(idOrPayload)` | `string` 或 `{ id / layerId }` | 停止粒子动画,图层仍可见。 |
|
|
2424
|
+
| `showWindField(idOrPayload)` | `string` 或 `{ id / layerId }` | 显示风场 Canvas。 |
|
|
2425
|
+
| `hideWindField(idOrPayload)` | `string` 或 `{ id / layerId }` | 隐藏风场 Canvas。 |
|
|
2426
|
+
| `removeWindField(idOrPayload)` | `string` 或 `{ id / layerId }` | 移除指定风场并解绑视图监听。 |
|
|
2427
|
+
| `clearWindFields()` | 无 | 移除全部风场。 |
|
|
2428
|
+
| `getState()` | 无 | 返回 `{ mounted, count, layers }`。 |
|
|
2429
|
+
|
|
2430
|
+
单个风场状态包含:
|
|
2431
|
+
|
|
2432
|
+
| 字段 | 说明 |
|
|
2433
|
+
| --- | --- |
|
|
2434
|
+
| `id` | 风场 id。 |
|
|
2435
|
+
| `valid` | 数据网格是否合法。 |
|
|
2436
|
+
| `visible` | 当前是否显示。 |
|
|
2437
|
+
| `running` | 当前是否播放动画。 |
|
|
2438
|
+
| `particleCount` | 当前粒子数量。 |
|
|
2439
|
+
| `bounds` | 风场数据范围 `{ west, south, east, north }`。 |
|
|
2440
|
+
| `center` | 风场中心 `{ lon, lat }`。 |
|
|
2441
|
+
|
|
804
2442
|
## 在 Vue 中封装 Hook
|
|
805
2443
|
|
|
806
2444
|
推荐页面用 hook 管理生命周期,组件只处理 UI。
|
|
@@ -822,8 +2460,20 @@ export function useBaseGIS(options = {}) {
|
|
|
822
2460
|
mapCore.value = null
|
|
823
2461
|
})
|
|
824
2462
|
|
|
2463
|
+
function switchEngine(engineType) {
|
|
2464
|
+
if (!mapCore.value || mapCore.value.getEngineType() === engineType) {
|
|
2465
|
+
return { success: true }
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
return mapCore.value.init({
|
|
2469
|
+
...options,
|
|
2470
|
+
engineType,
|
|
2471
|
+
})
|
|
2472
|
+
}
|
|
2473
|
+
|
|
825
2474
|
return {
|
|
826
2475
|
mapCore,
|
|
2476
|
+
switchEngine,
|
|
827
2477
|
}
|
|
828
2478
|
}
|
|
829
2479
|
```
|
|
@@ -838,13 +2488,22 @@ export function useBaseGIS(options = {}) {
|
|
|
838
2488
|
<script setup>
|
|
839
2489
|
import { useBaseGIS } from './useBaseGIS'
|
|
840
2490
|
|
|
841
|
-
const { mapCore } = useBaseGIS({
|
|
2491
|
+
const { mapCore, switchEngine } = useBaseGIS({
|
|
842
2492
|
engineType: 'cesium',
|
|
843
2493
|
containerId: 'map',
|
|
844
2494
|
})
|
|
845
2495
|
</script>
|
|
846
2496
|
```
|
|
847
2497
|
|
|
2498
|
+
如果页面有业务图层,`switchEngine()` 成功后要重新加载图层数据:
|
|
2499
|
+
|
|
2500
|
+
```js
|
|
2501
|
+
const result = switchEngine('leaflet')
|
|
2502
|
+
if (result.success) {
|
|
2503
|
+
await reloadBusinessLayers()
|
|
2504
|
+
}
|
|
2505
|
+
```
|
|
2506
|
+
|
|
848
2507
|
## 能力支持说明
|
|
849
2508
|
|
|
850
2509
|
| 能力 | Cesium | Leaflet |
|
|
@@ -861,6 +2520,8 @@ const { mapCore } = useBaseGIS({
|
|
|
861
2520
|
| 等值线 | 支持 | 支持 |
|
|
862
2521
|
| 等压线标注 | 支持 | 支持 |
|
|
863
2522
|
| 风场 Canvas 动画 | 支持 | 支持 |
|
|
2523
|
+
| 三维体渲染 | 支持 | 不支持 |
|
|
2524
|
+
| 三维切片 / 剖面渲染 | 支持 | 不支持 |
|
|
864
2525
|
| DEM 地形 | 支持 | 不支持 |
|
|
865
2526
|
|
|
866
2527
|
## 本地开发与打包
|
|
@@ -970,3 +2631,21 @@ mapCore.init()
|
|
|
970
2631
|
```
|
|
971
2632
|
|
|
972
2633
|
`init()` 内部会先销毁旧适配器,再创建新实例。
|
|
2634
|
+
|
|
2635
|
+
### 切换引擎后图层没了
|
|
2636
|
+
|
|
2637
|
+
这是预期行为。Cesium 和 Leaflet 的图层对象不能互相复用,`init({ engineType })` 会销毁旧地图实例并创建新地图实例。
|
|
2638
|
+
|
|
2639
|
+
处理方式是:页面或 store 保存业务数据,切换成功后重新调用对应的加载方法。
|
|
2640
|
+
|
|
2641
|
+
```js
|
|
2642
|
+
const result = mapCore.init({
|
|
2643
|
+
engineType: 'leaflet',
|
|
2644
|
+
containerId: 'map',
|
|
2645
|
+
})
|
|
2646
|
+
|
|
2647
|
+
if (result.success) {
|
|
2648
|
+
await imageLayer.update(currentImagePayload)
|
|
2649
|
+
await pointLayer.load({ points: currentPoints })
|
|
2650
|
+
}
|
|
2651
|
+
```
|