@anov/gis-skills-cli 0.0.0-stage → 0.3.3
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/CHANGELOG.md +637 -0
- package/INSTALL.md +481 -0
- package/LICENSE +15 -0
- package/README.md +148 -2
- package/RELEASING.md +162 -0
- package/bin/anov-gis-skills.mjs +470 -0
- package/lib/mcp-config.mjs +273 -0
- package/package.json +43 -4
- package/skills/anovgis-analysis/SKILL.md +585 -0
- package/skills/anovgis-effects/SKILL.md +260 -0
- package/skills/anovgis-imagery-terrain/SKILL.md +505 -0
- package/skills/anovgis-layers/SKILL.md +627 -0
- package/skills/anovgis-materials/SKILL.md +635 -0
- package/skills/anovgis-models-3dtiles/SKILL.md +448 -0
- package/skills/anovgis-pitfalls/SKILL.md +561 -0
- package/skills/anovgis-popup-widget/SKILL.md +474 -0
- package/skills/anovgis-primitives/SKILL.md +482 -0
- package/skills/anovgis-vector-graphics/SKILL.md +602 -0
- package/skills/anovgis-viewer/SKILL.md +618 -0
- package/skills/using-anovgis/DEMO-MAP.md +64 -0
- package/skills/using-anovgis/DEMO-SKILL-MAP.md +248 -0
- package/skills/using-anovgis/DOMAINS.md +183 -0
- package/skills/using-anovgis/REFERENCE.md +114 -0
- package/skills/using-anovgis/SKILL.md +392 -0
- package/skills/using-anovgis/templates/README.md +154 -0
- package/skills/using-anovgis/templates/combo1-vue3-vite.md +295 -0
- package/skills/using-anovgis/templates/combo2-vue2-cli.md +119 -0
- package/skills/using-anovgis/templates/combo3-html-cdn.md +107 -0
- package/skills/using-anovgis/templates/combo4-vanilla-webpack.md +91 -0
- package/skills/using-anovgis/templates/wizard-profiles.md +105 -0
- package/vendor/cesiumjs-skills/LICENSE +201 -0
- package/vendor/cesiumjs-skills/NOTICE +18 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-3d-tiles/SKILL.md +465 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-camera/SKILL.md +500 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-core-utilities/SKILL.md +403 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/REFERENCE.md +397 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/SKILL.md +351 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/01-diffuse-tint.js +38 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/02-texture-swap.js +42 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/03-feature-id-tileset.js +29 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/04-translucent-override.js +37 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/05-vertex-displacement.js +49 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/06-metadata-ramp.js +34 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/07-voxel-shader.js +27 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/README.md +19 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-custom-shader/examples/_sandcastle-template.html +9 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-entities/SKILL.md +389 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-imagery/SKILL.md +471 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-interaction/SKILL.md +423 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-materials-shaders/SKILL.md +292 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-models-particles/SKILL.md +423 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-primitives/SKILL.md +537 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-spatial-math/SKILL.md +358 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-terrain-environment/SKILL.md +401 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-time-properties/SKILL.md +353 -0
- package/vendor/cesiumjs-skills/skills/cesiumjs-viewer-setup/SKILL.md +434 -0
- package/vendor/cesiumjs-skills/skills/using-cesiumjs-skills/SKILL.md +35 -0
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: anovgis-layers
|
|
3
|
+
description: '@anov/gis 要素图层(14 个)。涵盖 VectorLayer / GeoJsonLayer / TopoJsonLayer / CzmlLayer / KmlLayer / GpxLayer / TilesetLayer / PrimitiveLayer / HtmlLayer / LabelLayer / ClusterLayer / GroundPrimitiveLayer / FeatureGridLayer / DynamicLayer,统一 viewer.addLayer / removeLayer / bindPopup / bindTooltip / addEventListener。触发关键词:图层、layer、GeoJSON、3D Tiles、CZML、KML、GPX、TopoJSON、ClusterLayer、HtmlLayer、FeatureGridLayer、addLayer、removeLayer、矢量瓦片、VectorTile、4490、切片加载、cluster 聚合、HTML 图层、CZML 时间轴、czml、playback、矢量瓦片 4490。Use when 加载 GeoJSON 行政区 / 3D Tiles 模型 / CZML 时序数据 / KML 标注 / 聚合点位 / DOM 叠加层 / 网格请求图层 / 4490 矢量瓦片 / 切片按视野分片加载。'
|
|
4
|
+
anov-gis-baseline: 1.8.6
|
|
5
|
+
cesium-baseline: 1.143.0
|
|
6
|
+
---
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# ANOVGIS 要素图层
|
|
10
|
+
|
|
11
|
+
> ⚠️ **优先级**:本 skill 优先于 SDK 源码 / `node_modules/@anov/gis/`。
|
|
12
|
+
> 遇到 API 行为疑问先查本 skill 与 `anovgis-pitfalls`。**严禁**主动 Glob/Grep `node_modules/@anov/gis/src/...` / `dist/...`;除非用户明确要求并承担风险。
|
|
13
|
+
> 调试流程见 `using-anovgis` § 默认调试流程(Chrome DevTools 仅第 5 级兜底)。
|
|
14
|
+
>
|
|
15
|
+
> **Cesium 入口(铁律)**:`const Cesium = window.Cesium`。`@anov/gis` 启动时已把 Cesium 挂到 `window`,**不存在** `ANOVGIS.Cesium` 写法;本 skill 所有 `Cesium.*` 均从此变量取。底层 Cesium API 细节查 `cesiumjs-skills` 对应 skill(API 名通用,`import` 写法换成 `const Cesium = window.Cesium`)。
|
|
16
|
+
|
|
17
|
+
`@anov/gis` 的 14 个要素图层类,负责矢量数据、模型、标注、聚合与 DOM 叠加。锁定 `@anov/gis` **v1.8.6**(Cesium **1.143.0**)。
|
|
18
|
+
|
|
19
|
+
影像底图 / 地形请用 `anovgis-imagery-terrain`;单个 Entity 图元(Point/Polyline/Polygon 等)请用 `anovgis-vector-graphics`;3D Tiles / Model 加载 + 抽壳 + 调色请用 `anovgis-models-3dtiles`。
|
|
20
|
+
|
|
21
|
+
## Out-of-scope(v0.2.0 短版)
|
|
22
|
+
|
|
23
|
+
- ❌ 不要写 `Tileset` 模型加载 + 拾取 + 抽壳 + 调色 → [`anovgis-models-3dtiles`](../anovgis-models-3dtiles/SKILL.md)
|
|
24
|
+
- ❌ 不要写离线 / WFS / 4490 / 内网 / 透明底图 / iServer 部署清单 → v0.3.0 `anovgis-offline-deployment`
|
|
25
|
+
- ❌ 不要写 Vector 16 类(Point / Polyline / ...)用法 → [`anovgis-vector-graphics`](../anovgis-vector-graphics/SKILL.md)
|
|
26
|
+
- ❌ 不要写 Primitive 19 类 → [`anovgis-primitives`](../anovgis-primitives/SKILL.md)
|
|
27
|
+
- ❌ 不要写 Popup / Tooltip 完整用法 → [`anovgis-popup-widget`](../anovgis-popup-widget/SKILL.md)
|
|
28
|
+
|
|
29
|
+
## 统一生命周期
|
|
30
|
+
|
|
31
|
+
类路径均在 `src/layer/graphic/`,全部继承 `Layer`(`src/layer/Layer.js`):
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
const layer = new ANOVGIS.VectorLayer();
|
|
35
|
+
viewer.addLayer(layer); // 接入
|
|
36
|
+
layer.bindPopup({ viewer }); // 绑定弹窗
|
|
37
|
+
layer.bindTooltip({ viewer }); // 绑定悬浮提示
|
|
38
|
+
layer.addEventListener(ANOVGIS.MouseEventType.CLICK, e => {});
|
|
39
|
+
layer.clear(); // 清空内容
|
|
40
|
+
viewer.removeLayer(layer); // 移除(传 layer 实例,不是 layer.id)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> ⚠️ **`removeLayer` 必须传 layer 实例**:源码 `src/base/viewer/Viewer.js:662` → `_removeLayer(layer)` 内部取 `layer.type` 和 `layer.id`(`Viewer.js:585`)。
|
|
44
|
+
> 传 `layer.id`(字符串)不会报错,但**层静默删不掉** —— `layer.type` 是 `undefined`,直接被 `hasOwnProperty` 挡掉。
|
|
45
|
+
|
|
46
|
+
## 图层速查表
|
|
47
|
+
|
|
48
|
+
| 类 | 构造函数 | 关键方法 | 备注 |
|
|
49
|
+
|---|---|---|---|
|
|
50
|
+
| `VectorLayer(opts?)` | `new VectorLayer()` | `addGraphic`, `eachGraphic`, `clear` | 最常用,自定义 Entity 容器(`CustomDataSource`) |
|
|
51
|
+
| `GeoJsonLayer(data, opts)` | `data` = url/对象/TopoJSON | `toVectorLayer()`, `toModelLayer(url)`, `eachGraphic(cb)` | 加载远端 URL 后可转 `VectorLayer` |
|
|
52
|
+
| `TopoJsonLayer(data, opts)` | 同上 | 继承 `GeoJsonLayer` | TopoJSON 格式 |
|
|
53
|
+
| `CzmlLayer(opts)` | `{ url, ... }` | `eachGraphic(cb)` | CZML 时序数据 |
|
|
54
|
+
| `KmlLayer(data, opts)` | `data` = url/对象 | `eachGraphic(cb)` | KML |
|
|
55
|
+
| `GpxLayer(opts)` | `{ url }` | `eachGraphic(cb)` | GPS 轨迹 |
|
|
56
|
+
| `TilesetLayer()` | 无参 | `addGraphic(tileset)`, `flyTo(...)` | 3D Tiles 容器;配合 `ANOVGIS.Tileset(url, opts)` |
|
|
57
|
+
| `PrimitiveLayer()` | 无参 | `.points` / `.labels` / `.billboards` / `.polylines` / `.primitives` / `.clouds` | 暴露 `Cesium.PrimitiveCollection` 子集 |
|
|
58
|
+
| `HtmlLayer(opts)` | `{ id }` | `addGraphic`, `flyTo`, `clear` | DOM 叠加层(`postRender` 同步位置) |
|
|
59
|
+
| `LabelLayer(opts)` | `{ url }` | 自动从 GeoJSON 抽 `entity.name` 转 `Label` | 大量 Label 优化 |
|
|
60
|
+
| `ClusterLayer(opts)` | `{ pixelRange, gradient, style, ... }` | `enableCluster`, `setHeight`, `clear` | 自动聚合;`style: 'circle' \| 'custom' \| 其他` |
|
|
61
|
+
| `GroundPrimitiveLayer()` | 无参 | `clear` | 贴地形 PrimitiveCollection |
|
|
62
|
+
| `FeatureGridLayer(opts)` | `{ url, tilingScheme, count, dataProperty, callback, maximumLevel }` | `clear`, `requestImage(x,y,lvl)` | 按瓦片请求后台拉数据并绘图 |
|
|
63
|
+
| `DynamicLayer(opts?)` | `{}` | `clear` | 通用动态 `CustomDataSource` |
|
|
64
|
+
|
|
65
|
+
## Snippets
|
|
66
|
+
|
|
67
|
+
<a id="s1"></a>
|
|
68
|
+
### S1. GeoJSON 行政区 + 样式
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
// 来源: examples/public/examples/html/geojsonLayer/polygon.html (L106-L116)
|
|
72
|
+
const style = {
|
|
73
|
+
stroke: Cesium.Color.fromCssColorString('rgba(46,145,229,1)'),
|
|
74
|
+
fill: Cesium.Color.fromCssColorString('rgba(46,145,229,0.3)'),
|
|
75
|
+
strokeWidth: 4, markerSize: 5, markerColor: Cesium.Color.CYAN
|
|
76
|
+
};
|
|
77
|
+
Cesium.GeoJsonDataSource.load(bj, style).then(ds => {
|
|
78
|
+
viewer.dataSources.add(ds);
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> `ANOVGIS.ApplyApi.createPolygonLayer` 提供业务封装(高亮 / 悬浮 / 文字标注),详见 `src/applyfn/applyBase.js`。
|
|
83
|
+
|
|
84
|
+
### S2. 3D Tiles + 鼠标拾取
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
// 来源: examples/public/examples/html/event/tilesetpopup.html (L48-L93)
|
|
88
|
+
const layer = new ANOVGIS.TilesetLayer();
|
|
89
|
+
viewer.addLayer(layer);
|
|
90
|
+
|
|
91
|
+
const tileset = new ANOVGIS.Tileset({
|
|
92
|
+
url: buildConfig.gisStatic + 'beijingchouxi/tileset.json',
|
|
93
|
+
highlight: { color: '#ff0000' },
|
|
94
|
+
selectedHighlight: { color: 'rgba(255,0,255,0.8)' }
|
|
95
|
+
});
|
|
96
|
+
tileset.setStyle(new ANOVGIS.Cesium3DTileStyle({
|
|
97
|
+
color: { conditions: [
|
|
98
|
+
['Number(${floor}) >= 40', 'rgba(45,0,75,0.5)'],
|
|
99
|
+
['true', 'rgb(127,59,8)']
|
|
100
|
+
]}
|
|
101
|
+
}));
|
|
102
|
+
layer.addGraphic(tileset);
|
|
103
|
+
|
|
104
|
+
layer.bindPopup({ viewer, showTitle: true, useDefaultHtmlTemplate: true });
|
|
105
|
+
layer.addEventListener(ANOVGIS.MouseEventType.CLICK, (e) => {
|
|
106
|
+
layer.popup.show(e.position, {
|
|
107
|
+
title: e.feature.getProperty('name1'),
|
|
108
|
+
fieldsMap: [{ nameC: '楼层', value: e.feature.getProperty('floor') }]
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
viewer.flyToTileset(tileset, 2, 0.5, -35);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### S3. VectorLayer 创建空容器 + addGraphic
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
// 来源: examples/public/examples/html/event/popup.html (L48-L92)
|
|
118
|
+
const layer = new ANOVGIS.VectorLayer({ id: 'pt-layer' });
|
|
119
|
+
viewer.addLayer(layer);
|
|
120
|
+
|
|
121
|
+
// 单个 Point + Popup
|
|
122
|
+
const v = new ANOVGIS.Point(position, {
|
|
123
|
+
color: ANOVGIS.Color.WHITE,
|
|
124
|
+
pixelSize: 12,
|
|
125
|
+
outlineColor: ANOVGIS.Color.BLUE,
|
|
126
|
+
outlineWidth: 2,
|
|
127
|
+
label: { text: '文字标签', font: '25px sans-serif', color: '#ffff00',
|
|
128
|
+
clampToGround: true, verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
129
|
+
pixelOffset: new Cesium.Cartesian2(0, -12) }
|
|
130
|
+
});
|
|
131
|
+
v.bindPopup({ viewer, showTitle: true, useDefaultHtmlTemplate: true });
|
|
132
|
+
v.addEventListener(ANOVGIS.MouseEventType.CLICK, (e) => {
|
|
133
|
+
v.popup.show(e.position, e.graphic.infoData);
|
|
134
|
+
});
|
|
135
|
+
layer.addGraphic(v);
|
|
136
|
+
|
|
137
|
+
viewer.flyTo(layer);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
> `VectorLayer` 本质是 `CustomDataSource`,可与 Cesium 原生 Entity 混用;可加 `Point` / `Polyline` / `Polygon` / `Model` / `Billboard` / `Label`。
|
|
141
|
+
|
|
142
|
+
### S4. GeoJsonLayer.toVectorLayer() 完整链
|
|
143
|
+
|
|
144
|
+
```js
|
|
145
|
+
// 来源: examples/public/examples/html/geojsonLayer/cluster.html (L36-L60)
|
|
146
|
+
// + graphics/divInfo2.html (L269-L294)
|
|
147
|
+
let layer = new ANOVGIS.GeoJsonLayer('../modelData/json/shanxi2.json');
|
|
148
|
+
layer = await layer.toVectorLayer(); // 拿到统一 VectorLayer
|
|
149
|
+
viewer.addLayer(layer);
|
|
150
|
+
viewer.flyTo(layer);
|
|
151
|
+
|
|
152
|
+
layer.eachGraphic(v => { // v 是 Polygon / Polyline / Billboard
|
|
153
|
+
let poss = [].concat(...v.positions, v.positions[0]); // 闭合环
|
|
154
|
+
v.setOptions({
|
|
155
|
+
material: Cesium.Color.fromCssColorString('#1b3377'),
|
|
156
|
+
fill: true,
|
|
157
|
+
polyline: { positions: poss, width: 1,
|
|
158
|
+
material: Cesium.Color.fromCssColorString('#52b3f0') }
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
> `toVectorLayer()` 内部按 entity 类型分派 `Billboard / Point / Polyline / Polygon / Label`;模型点位用 `toModelLayer(modelUrl)` 替身。
|
|
164
|
+
|
|
165
|
+
### S5. VectorLayer bindPopup / highlight / tooltip 三件套
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
// 来源: examples/public/examples/html/event/highlight.html (L60-L132)
|
|
169
|
+
const layer = new ANOVGIS.VectorLayer({ id: 'layer' });
|
|
170
|
+
viewer.addLayer(layer);
|
|
171
|
+
|
|
172
|
+
const pointOption = {
|
|
173
|
+
color: ANOVGIS.Color.WHITE, pixelSize: 12,
|
|
174
|
+
outlineColor: ANOVGIS.Color.BLUE, outlineWidth: 2,
|
|
175
|
+
label: { text: '文字标签', font: '25px sans-serif', color: '#ffff00',
|
|
176
|
+
clampToGround: true, verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
177
|
+
pixelOffset: new Cesium.Cartesian2(0, -12) },
|
|
178
|
+
infoData: { title: '标题',
|
|
179
|
+
fieldsMap: [{ nameC: '编号', value: 123 },
|
|
180
|
+
{ nameC: '姓名', value: '单位名称' }] },
|
|
181
|
+
highlight: { pixelSize: 17, outlineColor: '#ff0000', outlineWidth: 3 } // 滑过样式
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
positions.forEach((p, i) => {
|
|
185
|
+
const opt = Cesium.clone(pointOption, true);
|
|
186
|
+
opt.infoData.title = `第${i}个标题`;
|
|
187
|
+
const point = new ANOVGIS.Point(p, opt);
|
|
188
|
+
point.bindTooltip({ viewer, showTitle: true, offsetY: '-10', useDefaultHtmlTemplate: true });
|
|
189
|
+
point.addEventListener(ANOVGIS.MouseEventType.MOUSE_MOVE, (e) => {
|
|
190
|
+
point.tooltip.show(e.position, e.graphic.infoData);
|
|
191
|
+
});
|
|
192
|
+
layer.addGraphic(point);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
layer.bindPopup({ viewer, showTitle: true });
|
|
196
|
+
layer.addEventListener(ANOVGIS.MouseEventType.CLICK, (e) => {
|
|
197
|
+
layer.popup.show(e.position, e.graphic.infoData);
|
|
198
|
+
});
|
|
199
|
+
viewer.flyTo(layer);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
> `infoData` 字段是默认 Popup / Tooltip 模板的输入;非默认模板时 `popup.show(pos, '<html-string>')`。
|
|
203
|
+
|
|
204
|
+
### S6. CzmlLayer 时序数据 + clock 配置
|
|
205
|
+
|
|
206
|
+
```js
|
|
207
|
+
// 来源: SDK src/layer/graphic/CzmlLayer.js (L1-L43) + Cesium CzmlDataSource 标准用法
|
|
208
|
+
const layer = new ANOVGIS.CzmlLayer({ url: '/data/path.czml' });
|
|
209
|
+
viewer.addLayer(layer);
|
|
210
|
+
|
|
211
|
+
// 时序播放:把数据自带 clock 设到 viewer
|
|
212
|
+
layer.eachGraphic(() => {}); // 先触发 load 解析(可选)
|
|
213
|
+
viewer.clock.shouldAnimate = true;
|
|
214
|
+
viewer.clock.multiplier = 2; // 2× 速
|
|
215
|
+
viewer.timeline.zoomTo(layer._nativeObjCesium // Cesium Promise CzmlDataSource
|
|
216
|
+
? layer._nativeObjCesium.clock.startTime
|
|
217
|
+
: Cesium.JulianDate.now(),
|
|
218
|
+
layer._nativeObjCesium.clock.stopTime);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
> CZML 自带 `availability` / `epoch` 字段,会自动生成 `Clock`;加载完成后 `viewer.dataSources` 内已注册,无需手动播放控制;若想停表动画 `viewer.clock.shouldAnimate = false`。
|
|
222
|
+
|
|
223
|
+
### S7. TilesetLayer 3D Tiles + ready 回调 + click 拾取
|
|
224
|
+
|
|
225
|
+
```js
|
|
226
|
+
// 来源: examples/public/examples/html/event/tilesetpopup.html (L48-L108) + src/graphic/model/Tileset.js
|
|
227
|
+
const layer = new ANOVGIS.TilesetLayer();
|
|
228
|
+
viewer.addLayer(layer);
|
|
229
|
+
|
|
230
|
+
const tileset = new ANOVGIS.Tileset({
|
|
231
|
+
url: buildConfig.gisStatic + 'model/tileset.json',
|
|
232
|
+
highlight: { color: '#ff0000' }, // 滑过
|
|
233
|
+
selectedHighlight: { color: 'rgba(255,0,255,0.8)' } // 选中
|
|
234
|
+
});
|
|
235
|
+
tileset.ready(ts => { // 加载完成回调
|
|
236
|
+
ts.pointShadowing.enabled = true;
|
|
237
|
+
console.log('tileset ready', ts);
|
|
238
|
+
});
|
|
239
|
+
layer.addGraphic(tileset);
|
|
240
|
+
|
|
241
|
+
layer.bindPopup({ viewer, showTitle: true, useDefaultHtmlTemplate: true });
|
|
242
|
+
layer.bindTooltip({ viewer, showTitle: false, offsetY: '-10', useDefaultHtmlTemplate: true });
|
|
243
|
+
layer.addEventListener(ANOVGIS.MouseEventType.CLICK, (e) => {
|
|
244
|
+
layer.popup.show(e.position, {
|
|
245
|
+
title: e.feature.getProperty('name1'),
|
|
246
|
+
fieldsMap: [{ nameC: '楼层', value: e.feature.getProperty('floor') }]
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
layer.addEventListener(ANOVGIS.MouseEventType.MOUSE_MOVE, (e) => {
|
|
250
|
+
layer.tooltip.show(e.position, e.feature.getProperty('name1'));
|
|
251
|
+
});
|
|
252
|
+
viewer.flyToTileset(tileset, 2, 0.5, -35);
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
> Cesium 1.143 已删除 `readyEvent`,统一 `Cesium3DTileset.fromUrl()` 返回 Promise;SDK 用 `tileset.ready(cb)` 兜底。
|
|
256
|
+
|
|
257
|
+
<a id="s8"></a>
|
|
258
|
+
### S8. ClusterLayer 聚合 + 自定义图标
|
|
259
|
+
|
|
260
|
+
```js
|
|
261
|
+
// 来源: examples/public/examples/html/geojsonLayer/cluster.html (L87-L153)
|
|
262
|
+
// + SDK src/layer/graphic/ClusterLayer.js
|
|
263
|
+
const layer = new ANOVGIS.ClusterLayer({
|
|
264
|
+
style: 'circle', // 'circle' | 'custom' | 其他(蛛网)
|
|
265
|
+
pixelRange: 40,
|
|
266
|
+
gradient: { 0.0001: Cesium.Color.fromCssColorString('#928875'),
|
|
267
|
+
0.001: Cesium.Color.fromCssColorString('#928875'),
|
|
268
|
+
0.01: Cesium.Color.fromCssColorString('#928875'),
|
|
269
|
+
0.1: Cesium.Color.fromCssColorString('#928875') },
|
|
270
|
+
fontColor: Cesium.Color.fromCssColorString('#f0f0f0'),
|
|
271
|
+
boderColor: Cesium.Color.fromCssColorString('#ffd673'),
|
|
272
|
+
outColor: Cesium.Color.fromCssColorString('#ffd673').withAlpha(0.2),
|
|
273
|
+
});
|
|
274
|
+
viewer.addLayer(layer);
|
|
275
|
+
|
|
276
|
+
data.forEach(v => {
|
|
277
|
+
const pos = `${v.longitude},${v.latitude},0`;
|
|
278
|
+
layer.addGraphic(new ANOVGIS.Billboard(pos, { image: './assets/camera.png' }));
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
layer.bindPopup({ viewer, showTitle: false, useDefaultHtmlTemplate: true });
|
|
282
|
+
layer.addEventListener(ANOVGIS.MouseEventType.CLICK, (e) => {
|
|
283
|
+
layer.popup.show(e.position, e.graphic.name);
|
|
284
|
+
});
|
|
285
|
+
// 聚合点点击:缩放到子项
|
|
286
|
+
viewer.addEventListener(ANOVGIS.MouseEventType.CLICK, (e) => {
|
|
287
|
+
const ce = e.clusterEntity;
|
|
288
|
+
if (ce) {
|
|
289
|
+
const target = ce.id || ce.label?.id;
|
|
290
|
+
if (target) viewer.flyTo(target, 2, 0, -90, 0);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
> `style: 'custom'` 时 `gradient` 的 value 直接当 `image` 字符串(base64 dataURL 或 URL);`enableCluster = false` 可关聚合。
|
|
296
|
+
|
|
297
|
+
<a id="s9"></a>
|
|
298
|
+
### S9. HtmlLayer DOM 叠加 + 绝对定位 div
|
|
299
|
+
|
|
300
|
+
```js
|
|
301
|
+
// 来源: examples/public/examples/html/graphics/divInfo.html (L111-L135)
|
|
302
|
+
// + graphics/divInfo2.html (L165-L268)
|
|
303
|
+
const layer = new ANOVGIS.HtmlLayer({ layerName: 'info' });
|
|
304
|
+
viewer.addLayer(layer);
|
|
305
|
+
|
|
306
|
+
const div = new ANOVGIS.DivIcon(
|
|
307
|
+
new ANOVGIS.Position(116.38105869, 39.10115627, 1),
|
|
308
|
+
`<div class="boxbg">
|
|
309
|
+
<img class="div-img" src="../modelData/images/gyqy.png" />
|
|
310
|
+
<div class="div-right">天然纤维是自然界原有的...</div>
|
|
311
|
+
<div class="div-bottom">
|
|
312
|
+
<div class="div-info">河北棉花</div>
|
|
313
|
+
<div class="div-info">新疆棉花</div>
|
|
314
|
+
</div>
|
|
315
|
+
</div>`
|
|
316
|
+
);
|
|
317
|
+
div.setOptions({
|
|
318
|
+
horizontalOrigin: 'CENTER', verticalOrigin: 'TOP', // 对齐锚点
|
|
319
|
+
offsetX: 0, offsetY: -60,
|
|
320
|
+
pointerEvents: true, // 开启后 DOM 可交互
|
|
321
|
+
scaleByDistance: { near: 0, nearValue: 1.0, far: 10000, farValue: 0.0 }
|
|
322
|
+
});
|
|
323
|
+
div.addEventListener(ANOVGIS.MouseEventType.CLICK, () => alert('点击了'));
|
|
324
|
+
layer.addGraphic(div);
|
|
325
|
+
|
|
326
|
+
viewer.flyTo(layer, 3, 0, -60, 100); // 自动取所有 graphic 位置 flyTo
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
> `HtmlLayer` 通过 `scene.postRender` 每帧把 `cartesianToCanvasCoordinates` 写到 DOM `transform`;DOM 节点建议 < 1000,否则掉帧。`pointerEvents:false` 时 DOM 不接收事件,鼠标穿透到 Cesium 拾取。
|
|
330
|
+
|
|
331
|
+
### S10. Primitive 版海量点 marker — `geojsonLayer/primitiveMarker.html` L23-L227
|
|
332
|
+
|
|
333
|
+
```js
|
|
334
|
+
// 来源: primitiveMarker.html L171-217
|
|
335
|
+
// 用 Cesium 原生 PointPrimitiveCollection 做海量点(不走 SDK Entity,性能更好)
|
|
336
|
+
const collection = viewer.scene.primitives.add(new Cesium.PointPrimitiveCollection());
|
|
337
|
+
function addPoint([lng, lat, height], style) {
|
|
338
|
+
collection.add({
|
|
339
|
+
position: Cesium.Cartesian3.fromDegrees(lng, lat, height || 0),
|
|
340
|
+
color: Cesium.Color.fromCssColorString(style.color),
|
|
341
|
+
pixelSize: style.pixelSize,
|
|
342
|
+
outlineColor: Cesium.Color.fromCssColorString(style.outlineColor),
|
|
343
|
+
outlineWidth: style.outlineWidth,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
// 备选(被注释): ANOVGIS.ApplyApi.createClusterLayer / createPointLayer
|
|
347
|
+
// ANOVGIS.ApplyApi.createClusterLayer(viewer).createCluster({
|
|
348
|
+
// pointList, gradient: ['rgba(186,53,0,0.8)', ...], infoHtml,
|
|
349
|
+
// isHover, isClick, pointClick
|
|
350
|
+
// });
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### S11. 矢量墙体(Wall) — `geojsonLayer/wall.html` L23-L84
|
|
354
|
+
|
|
355
|
+
```js
|
|
356
|
+
// 来源: wall.html L35-66
|
|
357
|
+
// 用 viewer.entities 原生 + WallFlowMaterialProperty 流光
|
|
358
|
+
const wallEntity = viewer.entities.add({
|
|
359
|
+
name: '矢量墙体',
|
|
360
|
+
wall: {
|
|
361
|
+
positions: Cesium.Cartesian3.fromDegreesArray(position),
|
|
362
|
+
maximumHeights: new Array(positions.length).fill(1000),
|
|
363
|
+
minimumHeights: new Array(positions.length).fill(0),
|
|
364
|
+
material: Cesium.Color.fromCssColorString('rgba(255,255,0,0.5)'),
|
|
365
|
+
outline: true,
|
|
366
|
+
outlineColor: Cesium.Color.fromCssColorString('rgba(255,255,0,1)'),
|
|
367
|
+
},
|
|
368
|
+
});
|
|
369
|
+
viewer.flyTo(wallEntity);
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### S12. 墙体楼块(双层渲染) — `geojsonLayer/wallBuilds.html` L23-L180
|
|
373
|
+
|
|
374
|
+
```js
|
|
375
|
+
// 来源: wallBuilds.html L72-L177
|
|
376
|
+
// 演示墙体(Entity + WallFlowMaterialProperty) + 楼顶(GeoJsonDataSource) 双层
|
|
377
|
+
function addWall(positions, entity) {
|
|
378
|
+
for (let cor of positions) {
|
|
379
|
+
const wallObj = {
|
|
380
|
+
name: entity.name,
|
|
381
|
+
wall: {
|
|
382
|
+
positions: Cesium.Cartesian3.fromDegreesArray(handleCoordinates(cor.coordinates)),
|
|
383
|
+
maximumHeights: new Array(cor.coordinates.length).fill(cor.height),
|
|
384
|
+
minimumHeights: new Array(cor.coordinates.length).fill(0),
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
if (entity.isCustomMaterial && entity.material) {
|
|
388
|
+
wallObj.wall.material = entity.material;
|
|
389
|
+
} else if (!entity.isGradient) {
|
|
390
|
+
wallObj.wall.material = Cesium.Color.fromCssColorString(entity.color);
|
|
391
|
+
} else {
|
|
392
|
+
wallObj.wall.material = new ANOVGIS.WallFlowMaterialProperty({
|
|
393
|
+
color: Cesium.Color.fromCssColorString(entity.color),
|
|
394
|
+
duration: 2500
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
viewer.entities.add(wallObj);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
function addRoof(geojson, buildObj) {
|
|
401
|
+
Cesium.GeoJsonDataSource.load(geojson).then((datasource) => {
|
|
402
|
+
viewer.dataSources.add(datasource);
|
|
403
|
+
for (let entity of datasource.entities.values) {
|
|
404
|
+
const height = entity.properties['height'].getValue();
|
|
405
|
+
entity.polygon.height = height * floorHeight;
|
|
406
|
+
entity.polygon.material = Cesium.Color.fromCssColorString(buildObj.color);
|
|
407
|
+
entity.polygon.outline = buildObj.isOutline;
|
|
408
|
+
entity.polygon.outlineColor = Cesium.Color.fromCssColorString(buildObj.outlineColor);
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
<a id="s13"></a>
|
|
415
|
+
### S13. 天地图 WFS GeoJSON — `offlinemap/wfs.html` L29-L82
|
|
416
|
+
|
|
417
|
+
```js
|
|
418
|
+
// 来源: wfs.html L42-82
|
|
419
|
+
// 直接 Cesium.GeoJsonDataSource.load(不走 SDK helper),适合"想上色时仍可用原生 API"
|
|
420
|
+
window.viewer = new ANOVGIS.Viewer('cesiumContainer');
|
|
421
|
+
viewer.imageryLayers.addImageryProvider(
|
|
422
|
+
ANOVGIS.ImageryLayerFactory.createImageryLayer(ANOVGIS.ImageryType.TDT, {
|
|
423
|
+
style: 'img', key: globalConfig.tdtKey
|
|
424
|
+
})
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
function buildWfsUrl(config) {
|
|
428
|
+
const params = new URLSearchParams({
|
|
429
|
+
service: 'WFS', version: config.version, request: 'GetFeature',
|
|
430
|
+
typeName: config.layers, outputFormat: config.outputFormat, srsName: 'EPSG:4326',
|
|
431
|
+
});
|
|
432
|
+
return `${config.url}?${params.toString()}`;
|
|
433
|
+
}
|
|
434
|
+
const wfsConfig = {
|
|
435
|
+
url: 'http://gisserver.tianditu.gov.cn/TDTService/wfs',
|
|
436
|
+
layers: 'LRRL', // LRRL=铁路, LRDL=公路
|
|
437
|
+
version: '1.1.0', outputFormat: 'application/json',
|
|
438
|
+
};
|
|
439
|
+
const geoJsonData = await (await fetch(buildWfsUrl(wfsConfig))).json();
|
|
440
|
+
const dataSource = await Cesium.GeoJsonDataSource.load(geoJsonData, {
|
|
441
|
+
stroke: Cesium.Color.BLUE, strokeWidth: 2, strokeOpacity: 0.8
|
|
442
|
+
});
|
|
443
|
+
viewer.dataSources.add(dataSource);
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### S14. 河南高铁(虚实线 + layer 级 popup) — `offlinemap/railway.html` L116-L299
|
|
447
|
+
|
|
448
|
+
```js
|
|
449
|
+
// 来源: railway.html L127-L285
|
|
450
|
+
// 关键: dashPattern 区分隧道(虚线) / 市区 / 山区 / 平原 + layer 级 bindPopup
|
|
451
|
+
const railLayer = new ANOVGIS.VectorLayer();
|
|
452
|
+
viewer.addLayer(railLayer);
|
|
453
|
+
railLayer.bindPopup({ viewer, showTitle: true, horizontalOrigin: 'CENTER', verticalOrigin: 'TOP', useDefaultHtmlTemplate: true });
|
|
454
|
+
railLayer.addEventListener(ANOVGIS.MouseEventType.CLICK, (e) => {
|
|
455
|
+
if (e.graphic) railLayer.popup.show(e.position, e.graphic.infoData);
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
geoJsonData.features.forEach(feature => {
|
|
459
|
+
const props = feature.properties;
|
|
460
|
+
const isTunnel = props.tunnel === 'yes';
|
|
461
|
+
const lineDash = isTunnel ? [20, 10] : undefined; // 虚线 = 隧道
|
|
462
|
+
const infoData = {
|
|
463
|
+
title: '高铁线路信息',
|
|
464
|
+
fieldsMap: [
|
|
465
|
+
{ nameC: '线路名称:', value: props.name || '高铁线' },
|
|
466
|
+
{ nameC: '距市区:', value: props.distance + '米' },
|
|
467
|
+
],
|
|
468
|
+
};
|
|
469
|
+
coords.forEach(seg => {
|
|
470
|
+
const polyline = new ANOVGIS.Polyline(seg, {
|
|
471
|
+
material: lineColor, width: lineWidth,
|
|
472
|
+
dashPattern: lineDash, // 虚实线
|
|
473
|
+
infoData,
|
|
474
|
+
});
|
|
475
|
+
railLayer.addGraphic(polyline);
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(113.5, 34.0, 900000) });
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### S15. SuperMap iServer WMS + bindPopup — `offlinemap/iServerWmsCGI.html` L24-L90
|
|
482
|
+
|
|
483
|
+
```js
|
|
484
|
+
// 来源: iServerWmsCGI.html L27-89
|
|
485
|
+
// 关键: getFeatureInfoParameters 触发 GetFeatureInfo,selectedHighlight 点击高亮 + 弹字段表
|
|
486
|
+
const wms = ANOVGIS.ImageryLayerFactory.createImageryLayer(ANOVGIS.ImageryType.WMS, {
|
|
487
|
+
url: 'http://110.6.113.2:8090/iserver/services/map-nongda2608/wms111/CGI',
|
|
488
|
+
layers: '0',
|
|
489
|
+
parameters: { transparent: true, format: 'image/png' },
|
|
490
|
+
rectangle: Cesium.Rectangle.fromDegrees(119.799, 49.270, 120.110, 49.503),
|
|
491
|
+
getFeatureInfoParameters: { feature_count: 10 },
|
|
492
|
+
selectedHighlight: { material: 'rgba(255,255,0,0.6)', height: 0.01 },
|
|
493
|
+
});
|
|
494
|
+
wms.bindPopup({ viewer, showTitle: true, useDefaultHtmlTemplate: true });
|
|
495
|
+
wms.addEventListener(ANOVGIS.MouseEventType.CLICK, (e) => {
|
|
496
|
+
wms.popup.show(e.position, {
|
|
497
|
+
title: 'CGI 点击查询',
|
|
498
|
+
fieldsMap: Object.keys(e.feature.data.properties || {}).map(key => ({
|
|
499
|
+
nameC: key + ':', value: e.feature.data.properties[key] || '未知',
|
|
500
|
+
})),
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
viewer.imageryLayers.addImageryProvider(wms);
|
|
504
|
+
viewer.flyTo(wms);
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### S16. GeoJSON 点位 billboard(交替图片) — `geojsonLayer/billboard.html` L65-L101
|
|
508
|
+
|
|
509
|
+
```js
|
|
510
|
+
// 来源: billboard.html L65-L101
|
|
511
|
+
// 注:本 demo 未用 GeoJsonLayer,直接遍历 points 数组 + viewer.entities.add
|
|
512
|
+
function showPoints(points) {
|
|
513
|
+
const billboard1 = { image: '../modelData/images/upRule.png' };
|
|
514
|
+
const billboard2 = { image: '../modelData/images/underRule.png' };
|
|
515
|
+
let i = 1;
|
|
516
|
+
for (let position of points) {
|
|
517
|
+
if (i > 1000) break;
|
|
518
|
+
let lng = +position.lnglat[0], lat = +position.lnglat[1];
|
|
519
|
+
const entity = viewer.entities.add({
|
|
520
|
+
position: Cesium.Cartesian3.fromDegrees(lng, lat),
|
|
521
|
+
billboard: i % 2 === 0 ? billboard2 : billboard1, // 交替图片
|
|
522
|
+
});
|
|
523
|
+
i++;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### S17. GeoJSON 折线(原生命码) — `geojsonLayer/marker.html` L63-L74
|
|
529
|
+
|
|
530
|
+
```js
|
|
531
|
+
// 来源: marker.html L63-L74
|
|
532
|
+
// 注:文件名 marker.html 但内容是 polyline 演示
|
|
533
|
+
Cesium.GeoJsonDataSource.load(geojson).then((datasource) => {
|
|
534
|
+
viewer.dataSources.add(datasource);
|
|
535
|
+
for (let entity of datasource.entities.values) {
|
|
536
|
+
entity.polyline.width = 1;
|
|
537
|
+
entity.polyline.material = Cesium.Color.fromCssColorString('rgba(255,255,0,0.5)');
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### S18. GeoJSON 多边形楼块(基础版,绝对高度) — `geojsonLayer/polygonBuilds.html` L233-L264
|
|
543
|
+
|
|
544
|
+
```js
|
|
545
|
+
// 来源: polygonBuilds.html L233-L264
|
|
546
|
+
// 关键: 绝对高度(不贴地),适合无地形场景避免建筑漂移
|
|
547
|
+
Cesium.GeoJsonDataSource.load(geojson).then((datasource) => {
|
|
548
|
+
viewer.dataSources.add(datasource);
|
|
549
|
+
for (let entity of datasource.entities.values) {
|
|
550
|
+
let height = 0;
|
|
551
|
+
entity.polygon.height = 0; // 距椭球面 0 米
|
|
552
|
+
if (entity.properties.hasOwnProperty('height')) {
|
|
553
|
+
const val = entity.properties['height'].getValue();
|
|
554
|
+
if (!isNaN(val)) height = val - 0;
|
|
555
|
+
}
|
|
556
|
+
entity.polygon.extrudedHeight = height; // 从属性读拉伸高度
|
|
557
|
+
entity.polygon.outline = true;
|
|
558
|
+
entity.polygon.material = Cesium.Color.fromCssColorString('rgba(62,171,107,0.8)');
|
|
559
|
+
entity.polygon.outlineColor = Cesium.Color.fromCssColorString('rgba(62,171,107,0.4)');
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### S19. GeoJSON 多边形楼块(贴地 + floorHeight 倍率) — `geojsonLayer/polygonBuildsMaterial.html` L64-L89
|
|
565
|
+
|
|
566
|
+
```js
|
|
567
|
+
// 来源: polygonBuildsMaterial.html L64-89
|
|
568
|
+
// 关键: HeightReference.RELATIVE_TO_GROUND + extrudedHeight = height * 3(floorHeight)
|
|
569
|
+
const floorHeight = 3;
|
|
570
|
+
Cesium.GeoJsonDataSource.load(geojson).then((datasource) => {
|
|
571
|
+
viewer.dataSources.add(datasource);
|
|
572
|
+
for (let entity of datasource.entities.values) {
|
|
573
|
+
let height = 0;
|
|
574
|
+
entity.polygon.heightReference = Cesium.HeightReference.RELATIVE_TO_GROUND;
|
|
575
|
+
entity.polygon.height = 0;
|
|
576
|
+
entity.polygon.extrudedHeightReference = Cesium.HeightReference.RELATIVE_TO_GROUND;
|
|
577
|
+
if (entity.properties.hasOwnProperty('height')) {
|
|
578
|
+
const val = entity.properties['height'].getValue();
|
|
579
|
+
if (!isNaN(val)) height = val - 0;
|
|
580
|
+
}
|
|
581
|
+
entity.polygon.extrudedHeight = height * floorHeight; // 按层高 3 米拉伸
|
|
582
|
+
entity.polygon.outline = true;
|
|
583
|
+
entity.polygon.material = Cesium.Color.fromCssColorString('rgba(62,171,107,0.8)');
|
|
584
|
+
entity.polygon.outlineColor = Cesium.Color.fromCssColorString('rgba(62,171,107,0.4)');
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
### S20. GeoJSON 多边形楼块(自定义 GLSL 材质) — `geojsonLayer/polygonBuildsMaterial.html` L83-L122
|
|
590
|
+
|
|
591
|
+
```js
|
|
592
|
+
// 来源: polygonBuildsMaterial.html L83-L122
|
|
593
|
+
// 关键: 给每个 polygon 应用自定义 Cesium.Material,fabric 内嵌 GLSL 按 UV 输出颜色
|
|
594
|
+
entity.polygon.outline = false; // 关闭 outline
|
|
595
|
+
entity.polygon.material = new Cesium.Material({
|
|
596
|
+
translucent: false,
|
|
597
|
+
fabric: {
|
|
598
|
+
uniforms: {
|
|
599
|
+
// image / gradient / decoration 三个图片 uniform 按需填
|
|
600
|
+
},
|
|
601
|
+
source: `
|
|
602
|
+
czm_material czm_getMaterial(czm_materialInput materialInput) {
|
|
603
|
+
czm_material material = czm_getDefaultMaterial(materialInput);
|
|
604
|
+
// 按立面 UV 输出颜色(st ∈ [0,1])
|
|
605
|
+
material.diffuse = vec3(materialInput.st, 1.0);
|
|
606
|
+
material.alpha = 1.0;
|
|
607
|
+
return material;
|
|
608
|
+
}
|
|
609
|
+
`,
|
|
610
|
+
},
|
|
611
|
+
});
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
## 实战最佳实践
|
|
615
|
+
|
|
616
|
+
1. **`TilesetLayer` 容器 + `Tileset` 实例**:必须 `layer.addGraphic(tileset)` 之后才有 popup / 事件;定位用 `viewer.flyToTileset(tileset, duration, offsetX, pitch)`。
|
|
617
|
+
2. **GeoJSON 转 `VectorLayer`**:`geoJsonLayer.toVectorLayer()` 拿到统一容器;模型点位用 `toModelLayer(modelUrl)`。
|
|
618
|
+
3. **`ClusterLayer` 配色**:`gradient: { 阈值: 颜色, ... }` 按"占比"分档;`style: 'custom'` 时 value 直接当图片。
|
|
619
|
+
4. **`HtmlLayer` 性能**:DOM 节点 < 1000 较稳;大量点位改用 `LabelLayer` 或 `PrimitiveLayer.labels`。
|
|
620
|
+
5. **`FeatureGridLayer` 适用场景**:海量点位按视野瓦片分片拉取,`callback` 里自行绘制,避免一次性加载全量。
|
|
621
|
+
|
|
622
|
+
## 参考
|
|
623
|
+
|
|
624
|
+
- 图层基类:`src/layer/Layer.js`
|
|
625
|
+
- 要素图层:`src/layer/graphic/`
|
|
626
|
+
- 3D Tiles 封装:`ANOVGIS.Tileset` (`src/graphic/model/Tileset.js`)
|
|
627
|
+
- 业务封装:`src/applyfn/applyBase.js`
|