@mesh3d/cesium-vectortile-gl 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +120 -0
- package/Source/Cesium.d.ts +2692 -0
- package/Source/VectorTileLOD.js +494 -0
- package/Source/VectorTileRenderList.js +65 -0
- package/Source/VectorTileset.js +309 -0
- package/Source/layers/BackgroundRenderLayer.js +82 -0
- package/Source/layers/FillRenderLayer.js +18 -0
- package/Source/layers/IRenderLayer.js +128 -0
- package/Source/layers/LineRenderLayer.js +94 -0
- package/Source/layers/SymbolRenderLayer.js +31 -0
- package/Source/layers/index.js +16 -0
- package/Source/layers/registerRenderLayer.js +24 -0
- package/Source/layers/visualizers/FillLayerVisualizer.js +420 -0
- package/Source/layers/visualizers/ILayerVisualizer.js +73 -0
- package/Source/layers/visualizers/LineLayerVisualizer.js +565 -0
- package/Source/layers/visualizers/SymbolLayerVisualizer.js +179 -0
- package/Source/sources/GeoJSONSource.js +46 -0
- package/Source/sources/ISource.js +39 -0
- package/Source/sources/VectorSource.js +45 -0
- package/Source/sources/granularitySettings.js +20 -0
- package/Source/sources/index.js +11 -0
- package/Source/sources/registerSource.js +19 -0
- package/Source/style/StyleLayer.js +43 -0
- package/Source/style/StyleLayerProperties.js +43 -0
- package/Source/style/index.js +2 -0
- package/dist/cvt-gl.js +10642 -0
- package/dist/cvt-gl.js.map +1 -0
- package/dist/cvt-gl.min.js +135 -0
- package/dist/cvt-gl.min.js.map +1 -0
- package/index.js +6 -0
- package/logo.svg +47 -0
- package/package.json +36 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { VectorTileLOD } from "./VectorTileLOD"
|
|
2
|
+
import { StyleLayer } from "./style/StyleLayer"
|
|
3
|
+
import './layers/index'
|
|
4
|
+
import { VectorTileRenderList } from "./VectorTileRenderList"
|
|
5
|
+
import { Sources } from "./sources"
|
|
6
|
+
import { ISource } from "./sources/ISource"
|
|
7
|
+
import { warnOnce } from "maplibre-gl/src/util/util"
|
|
8
|
+
|
|
9
|
+
export class VectorTileset {
|
|
10
|
+
/**
|
|
11
|
+
* @param {object} options
|
|
12
|
+
* @param {string|import('@maplibre/maplibre-gl-style-spec').StyleSpecification} options.style
|
|
13
|
+
* @param {boolean} [options.showTileColor=false]
|
|
14
|
+
*/
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.maximumLevel = 24
|
|
17
|
+
this.show = true
|
|
18
|
+
this.showTileColor = !!options.showTileColor
|
|
19
|
+
this.ready = false
|
|
20
|
+
this.tilingScheme = new Cesium.WebMercatorTilingScheme()
|
|
21
|
+
|
|
22
|
+
this.readyEvent = new Cesium.Event()
|
|
23
|
+
this.errorEvent = new Cesium.Event()
|
|
24
|
+
|
|
25
|
+
this._styleJson = null
|
|
26
|
+
this._style = options.style
|
|
27
|
+
this._rootTiles = []
|
|
28
|
+
this._cacheTiles = []
|
|
29
|
+
this._tilesToRender = []
|
|
30
|
+
/**@type {StyleLayer[]} */
|
|
31
|
+
this._styleLayers = []
|
|
32
|
+
/**@type {VectorTileRenderList} */
|
|
33
|
+
this._renderList = new VectorTileRenderList(this._styleLayers)
|
|
34
|
+
this.numLoading = 0
|
|
35
|
+
this.numInitializing = 0
|
|
36
|
+
/**@type {Cesium.Texture} */
|
|
37
|
+
this.tileIdTexture = null
|
|
38
|
+
|
|
39
|
+
requestAnimationFrame(() => {
|
|
40
|
+
this.init()
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async init() {
|
|
45
|
+
let style = this._style
|
|
46
|
+
if (!style) {
|
|
47
|
+
this.errorEvent.raiseEvent(new Error('请传入 style 参数'))
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.path = ''
|
|
52
|
+
if (typeof style == 'string') {
|
|
53
|
+
this.path = style.split('/').slice(0, -1).join('/')
|
|
54
|
+
if (this.path) this.path += '/'
|
|
55
|
+
style = await Cesium.Resource.fetchJson(style)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//初始化数据源
|
|
59
|
+
|
|
60
|
+
/** @type {{[sourceId:string]:ISource}}*/
|
|
61
|
+
this.sources = {}
|
|
62
|
+
for (const sourceId in style.sources) {
|
|
63
|
+
/**@type {import('@maplibre/maplibre-gl-style-spec').SourceSpecification} */
|
|
64
|
+
const sourceParams = style.sources[sourceId]
|
|
65
|
+
const SourceCls = Sources[sourceParams.type]
|
|
66
|
+
if (SourceCls) {
|
|
67
|
+
this.sources[sourceId] = new SourceCls(sourceParams, this.path)
|
|
68
|
+
try {
|
|
69
|
+
await this.sources[sourceId].init()
|
|
70
|
+
this.maximumLevel = Math.min(sourceParams.maxzoom || 24, this.maximumLevel)
|
|
71
|
+
} catch (err) {
|
|
72
|
+
this.errorEvent.raiseEvent(err)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//初始化样式图层
|
|
78
|
+
for (let i = 0; i < style.layers.length; i++) {
|
|
79
|
+
this._styleLayers[i] = new StyleLayer(style.layers[i])
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//创建顶级瓦片LOD
|
|
83
|
+
const numX = this.tilingScheme.getNumberOfXTilesAtLevel(0)
|
|
84
|
+
const numY = this.tilingScheme.getNumberOfYTilesAtLevel(0)
|
|
85
|
+
let i = 0
|
|
86
|
+
for (let y = 0; y < numY; y++) {
|
|
87
|
+
for (let x = 0; x < numX; x++) {
|
|
88
|
+
var tile = new VectorTileLOD({
|
|
89
|
+
parent: this, x, y, z: 0,
|
|
90
|
+
tilingScheme: this.tilingScheme
|
|
91
|
+
})
|
|
92
|
+
tile.createChildren()
|
|
93
|
+
this._rootTiles[i++] = tile
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//初始化渲染队列
|
|
98
|
+
this._renderList.init()
|
|
99
|
+
|
|
100
|
+
this._styleJson = style
|
|
101
|
+
this.ready = true
|
|
102
|
+
this.readyEvent.raiseEvent(this)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//更新瓦片id纹理,用于裁剪超出瓦片边界的像素
|
|
106
|
+
executeTileIdCommands(frameState) {
|
|
107
|
+
const tileIdCommands = this._renderList.tileIdCommands
|
|
108
|
+
|
|
109
|
+
if (tileIdCommands.length > 0) {
|
|
110
|
+
const context = frameState.context
|
|
111
|
+
/**@type {Cesium.FrameBuffer} */
|
|
112
|
+
let tileIdFbo = this._tileIdFbo
|
|
113
|
+
if (!tileIdFbo) {
|
|
114
|
+
tileIdFbo = new Cesium.FramebufferManager({
|
|
115
|
+
depthStencil: true,
|
|
116
|
+
supportsDepthTexture: true,
|
|
117
|
+
})
|
|
118
|
+
this._tileIdFbo = tileIdFbo
|
|
119
|
+
this._idClearCommand = new Cesium.ClearCommand({
|
|
120
|
+
color: new Cesium.Color(0.0, 0.0, 0.0, 0.0),
|
|
121
|
+
depth: 1.0,
|
|
122
|
+
stencil: 0.0,
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
const pixelDatatype = context.floatingPointTexture
|
|
126
|
+
? Cesium.PixelDatatype.FLOAT
|
|
127
|
+
: Cesium.PixelDatatype.UNSIGNED_BYTE;
|
|
128
|
+
const width = context.drawingBufferWidth
|
|
129
|
+
const height = context.drawingBufferHeight
|
|
130
|
+
tileIdFbo.update(context, width, height, 1, pixelDatatype)
|
|
131
|
+
tileIdFbo.clear(context, this._idClearCommand)
|
|
132
|
+
|
|
133
|
+
const framebuffer = tileIdFbo.framebuffer
|
|
134
|
+
for (const tileIdCommand of tileIdCommands) {
|
|
135
|
+
tileIdCommand.framebuffer = framebuffer
|
|
136
|
+
tileIdCommand.execute(context)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.tileIdTexture = tileIdFbo.getColorTexture(0)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
update(frameState) {
|
|
144
|
+
if (!this.ready || !this.show) return
|
|
145
|
+
|
|
146
|
+
if (frameState.context.webgl2) {
|
|
147
|
+
warnOnce('webgl2模式下贴地线面的支持将导致性能下降')
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const renderList = this._renderList
|
|
151
|
+
//清空渲染队列
|
|
152
|
+
renderList.beginFrame()
|
|
153
|
+
|
|
154
|
+
this.numInitializing = 0
|
|
155
|
+
|
|
156
|
+
/**@type {Cesium.Globe} */
|
|
157
|
+
const scene = frameState.camera._scene
|
|
158
|
+
const globe = scene.globe
|
|
159
|
+
const globeSuspendLodUpdate = globe._surface._debug.suspendLodUpdate
|
|
160
|
+
this.scene = scene
|
|
161
|
+
|
|
162
|
+
// 获取可见瓦片
|
|
163
|
+
// 优化:采用更高效的LOD调度算法,获取当前帧实际可渲染到屏幕的瓦片,避免出现瓦片层级切换时候出现闪烁
|
|
164
|
+
|
|
165
|
+
/**@type {VectorTileLOD[]} */
|
|
166
|
+
const tilesToRender = globeSuspendLodUpdate ? this._tilesToRender : getTilesToRender(frameState, this)
|
|
167
|
+
|
|
168
|
+
//瓦片排序,决定瓦片加载瓦片数据、初始化的优先级
|
|
169
|
+
//优化:采用更精细、高效的优先级策略
|
|
170
|
+
if (!globeSuspendLodUpdate) {
|
|
171
|
+
tilesToRender.sort((a, b) => a.distanceToCamera - b.distanceToCamera)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
//更新瓦片状态:请求瓦片数据,创建渲染图层,初始化等
|
|
175
|
+
for (const tile of tilesToRender) {
|
|
176
|
+
tile.lastVisitTime = frameState.frameNumber
|
|
177
|
+
tile.expired = false
|
|
178
|
+
tile.update(frameState, renderList, this)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
//渲染图层分组、排序
|
|
182
|
+
const orderedRenderLayers = renderList.getList()
|
|
183
|
+
//获取渲染命令(DrawCommand),渲染图层内部可以使用Primitive、PolylineCollection、LabelCollection、BillboardCollection等API,
|
|
184
|
+
//也可以自定义DrawCommand
|
|
185
|
+
for (const renderLayer of orderedRenderLayers) {
|
|
186
|
+
renderLayer.update(frameState, this)
|
|
187
|
+
}
|
|
188
|
+
//瓦片颜色、深度
|
|
189
|
+
frameState.commandList.push(...renderList.tileCommands)
|
|
190
|
+
|
|
191
|
+
this.executeTileIdCommands(frameState)
|
|
192
|
+
|
|
193
|
+
//释放过期瓦片
|
|
194
|
+
//优化:使用更高效的内存缓存管理策略
|
|
195
|
+
const expiredTiles = []
|
|
196
|
+
for (const cacheTile of this._cacheTiles) {
|
|
197
|
+
if (cacheTile.lastVisitTime < frameState.frameNumber) {
|
|
198
|
+
if (!cacheTile.expired) expiredTiles.push(cacheTile)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
expiredTiles.sort((a, b) => a.lastVisitTime - b.lastVisitTime)
|
|
202
|
+
if (expiredTiles.length > 100) {
|
|
203
|
+
for (const expiredTile of expiredTiles) {
|
|
204
|
+
expiredTile.unload()
|
|
205
|
+
expiredTile.expired = true
|
|
206
|
+
if (expiredTiles.length <= 50) break
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
destroy() {
|
|
212
|
+
const scene = this.scene
|
|
213
|
+
const rootTiles = this._rootTiles
|
|
214
|
+
this.scene = null
|
|
215
|
+
if (scene && scene.primitives.contains(this)) {
|
|
216
|
+
scene.primitives.remove(this)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (rootTiles) {
|
|
220
|
+
for (const tile of rootTiles) {
|
|
221
|
+
tile.destroy()
|
|
222
|
+
}
|
|
223
|
+
rootTiles.length = 0
|
|
224
|
+
this._rootTiles = null
|
|
225
|
+
}
|
|
226
|
+
if (this._cacheTiles) {
|
|
227
|
+
this._cacheTiles.length = 0
|
|
228
|
+
this._cacheTiles = null
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (this.sources) {
|
|
232
|
+
for (const key in this.sources) {
|
|
233
|
+
if (Object.hasOwnProperty.call(this.sources, key)) {
|
|
234
|
+
const source = this.sources[key];
|
|
235
|
+
source.destroy()
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
this.sources = null
|
|
239
|
+
}
|
|
240
|
+
this._styleLayers = null
|
|
241
|
+
|
|
242
|
+
if (this._renderList) {
|
|
243
|
+
this._renderList.destroy()
|
|
244
|
+
this._renderList = null
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (this._tilesToRender) {
|
|
248
|
+
this._tilesToRender.length = 0
|
|
249
|
+
this._tilesToRender = null
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (this._tileIdFbo) {
|
|
253
|
+
this._tileIdFbo.destroy()
|
|
254
|
+
this.tileIdTexture = null
|
|
255
|
+
this._tileIdFbo = null
|
|
256
|
+
this._idClearCommand = null
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
this._styleJson = null
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
isDestroyed() {
|
|
263
|
+
return false
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 遍历LOD四叉树,获取所有可见瓦片
|
|
269
|
+
* @param {Cesium.FrameState} frameState
|
|
270
|
+
* @param {VectorTileset} tileset
|
|
271
|
+
* @returns
|
|
272
|
+
*/
|
|
273
|
+
function getTilesToRender(frameState, tileset) {
|
|
274
|
+
const queue = [
|
|
275
|
+
...tileset._rootTiles
|
|
276
|
+
]
|
|
277
|
+
const tilesToRender = tileset._tilesToRender
|
|
278
|
+
const visitor = {
|
|
279
|
+
//当see大于阈值,继续查找子级瓦片
|
|
280
|
+
visitChildren(tile) {
|
|
281
|
+
if (tile.z >= tileset.maximumLevel) {
|
|
282
|
+
return tilesToRender.push(tile)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (tile.children.length == 0) {
|
|
286
|
+
tile.createChildren()
|
|
287
|
+
for (const child of tile.children) {
|
|
288
|
+
tileset._cacheTiles.push(child)
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
for (const child of tile.children) {
|
|
292
|
+
queue.push(child)
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
//否则使用当前瓦片填充视口
|
|
296
|
+
accept(tile) {
|
|
297
|
+
tilesToRender.push(tile)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
tilesToRender.length = 0
|
|
302
|
+
|
|
303
|
+
do {
|
|
304
|
+
const tile = queue.shift()
|
|
305
|
+
tile.visit(frameState, visitor)
|
|
306
|
+
} while (queue.length > 0);
|
|
307
|
+
|
|
308
|
+
return tilesToRender
|
|
309
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { VectorTileset } from '../VectorTileset'
|
|
2
|
+
import { IRenderLayer } from './IRenderLayer'
|
|
3
|
+
import { registerRenderLayer } from './registerRenderLayer'
|
|
4
|
+
import { warnOnce } from 'maplibre-gl/src/util/util'
|
|
5
|
+
|
|
6
|
+
export class BackgroundRenderLayer extends IRenderLayer {
|
|
7
|
+
createPrimitve(frameState, tileset) {
|
|
8
|
+
const style = this.style
|
|
9
|
+
const tile = this.tile
|
|
10
|
+
const color = style.convertColor(style.paint.getDataConstValue('background-color', tile.z))
|
|
11
|
+
const opacity = style.paint.getDataConstValue('background-opacity', tile.z)
|
|
12
|
+
const pattern = style.paint.getDataConstValue('background-pattern', tile.z)
|
|
13
|
+
if (pattern) {
|
|
14
|
+
return warnOnce('background图层:不支持纹理填充')
|
|
15
|
+
}
|
|
16
|
+
color.alpha *= opacity
|
|
17
|
+
|
|
18
|
+
const primitive = new Cesium.Primitive({
|
|
19
|
+
geometryInstances: new Cesium.GeometryInstance({
|
|
20
|
+
geometry: new Cesium.RectangleGeometry({
|
|
21
|
+
rectangle: this.tile.rectangle
|
|
22
|
+
}),
|
|
23
|
+
}),
|
|
24
|
+
compressVertices: false,
|
|
25
|
+
asynchronous: false,
|
|
26
|
+
appearance: new Cesium.MaterialAppearance({
|
|
27
|
+
translucent: false,
|
|
28
|
+
material: Cesium.Material.fromType('Color', {
|
|
29
|
+
color: color
|
|
30
|
+
}),
|
|
31
|
+
flat: true
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
this.primitive = primitive
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {Cesium.FrameState} frameState
|
|
40
|
+
* @param {VectorTileset} tileset
|
|
41
|
+
*/
|
|
42
|
+
update(frameState, tileset) {
|
|
43
|
+
if (!this.primitive) {
|
|
44
|
+
this.createPrimitve(frameState, tileset)
|
|
45
|
+
}
|
|
46
|
+
if (this.primitive && !this.commandList.length) {
|
|
47
|
+
const preCommandList = frameState.commandList
|
|
48
|
+
const layerCommandList = frameState.commandList = this.commandList
|
|
49
|
+
|
|
50
|
+
this.primitive.update(frameState)
|
|
51
|
+
|
|
52
|
+
//DrawCommand创建完成后,关闭深度写入,开启深度测试
|
|
53
|
+
if (layerCommandList.length > 0) {
|
|
54
|
+
const renderState = Cesium.RenderState.fromCache({
|
|
55
|
+
blending: Cesium.BlendingState.ALPHA_BLEND,
|
|
56
|
+
depthMask: false,
|
|
57
|
+
depthTest: {
|
|
58
|
+
enabled: true
|
|
59
|
+
},
|
|
60
|
+
cull: {
|
|
61
|
+
enabled: true
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
for (const layerCommand of layerCommandList) {
|
|
65
|
+
layerCommand.renderState = renderState
|
|
66
|
+
layerCommand.pass = Cesium.Pass.CESIUM_3D_TILE
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
frameState.commandList = preCommandList
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
super.update(frameState, tileset)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
destroy() {
|
|
77
|
+
this.primitive = this.primitive && this.primitive.destroy()
|
|
78
|
+
super.destroy()
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
registerRenderLayer('background', BackgroundRenderLayer)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { VectorTileset } from '../VectorTileset'
|
|
2
|
+
import { IRenderLayer } from './IRenderLayer'
|
|
3
|
+
import { registerRenderLayer } from './registerRenderLayer'
|
|
4
|
+
import { FillLayerVisualizer } from './visualizers/FillLayerVisualizer'
|
|
5
|
+
|
|
6
|
+
export class FillRenderLayer extends IRenderLayer {
|
|
7
|
+
/**
|
|
8
|
+
* @param {Cesium.FrameState} frameState
|
|
9
|
+
* @param {VectorTileset} tileset
|
|
10
|
+
*/
|
|
11
|
+
update(frameState, tileset) {
|
|
12
|
+
//可以在这里实现同步样式,动态更新图层颜色等样式
|
|
13
|
+
|
|
14
|
+
super.update(frameState, tileset)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
registerRenderLayer('fill', FillRenderLayer, FillLayerVisualizer)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as MVT from '@mapbox/vector-tile'
|
|
2
|
+
import { StyleLayer } from '../style/StyleLayer'
|
|
3
|
+
import { VectorTileset } from '../VectorTileset'
|
|
4
|
+
import { VectorTileLOD } from '../VectorTileLOD'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 渲染要素接口,对应数据要素中的一个图形(例如 MultiLineString 中的1个多段线)
|
|
8
|
+
*/
|
|
9
|
+
export class IRenderFeature {
|
|
10
|
+
constructor() {
|
|
11
|
+
//如下2个属性用于表达式取值
|
|
12
|
+
this.id = null
|
|
13
|
+
this.properties = {}
|
|
14
|
+
|
|
15
|
+
//如下2个属性用于同步图层样式
|
|
16
|
+
this.batchId = 0
|
|
17
|
+
this.featureId = 0
|
|
18
|
+
|
|
19
|
+
//可选,批量构建几何体可能需要临时存储,创建结束后应及时释放
|
|
20
|
+
this.coordinates = []
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 渲染图层基类,定义渲染图层的通用属性和方法(更新、销毁)
|
|
26
|
+
*/
|
|
27
|
+
export class IRenderLayer {
|
|
28
|
+
/**
|
|
29
|
+
* 构造渲染图层实例。注意:该构造函数由VectorTileset调用,请勿在其他模块直接调用
|
|
30
|
+
* @param {MVT.VectorTileFeature[]} sourceFeatures
|
|
31
|
+
* @param {StyleLayer} styleLayer
|
|
32
|
+
* @param {VectorTileLOD} tile
|
|
33
|
+
*/
|
|
34
|
+
constructor(sourceFeatures, styleLayer, tile) {
|
|
35
|
+
/**@type {MVT.VectorTileFeature[]} */
|
|
36
|
+
this.sourceFeatures = sourceFeatures
|
|
37
|
+
/**@type {StyleLayer} */
|
|
38
|
+
this.style = styleLayer
|
|
39
|
+
/**@type {VectorTileLOD} */
|
|
40
|
+
this.tile = tile
|
|
41
|
+
/**
|
|
42
|
+
* @type {IRenderFeature[]}
|
|
43
|
+
*/
|
|
44
|
+
this.features = []
|
|
45
|
+
|
|
46
|
+
//如下5个属性是图层渲染器专用,未定义相应类型图层渲染器的可以忽略
|
|
47
|
+
/**
|
|
48
|
+
* 图层渲染器构造几何体实例过程中,记录当前图层第一个实例的索引,这个索引与批次表及几何体顶点数组中的的batchId一致。
|
|
49
|
+
* 注意:该属性是针对图层渲染器设计,未定义相应类型图层渲染器的可以忽略
|
|
50
|
+
* @type {number}
|
|
51
|
+
*/
|
|
52
|
+
this.firstBatchId = -1
|
|
53
|
+
/**
|
|
54
|
+
* 图层渲染器构造几何体实例过程中,记录当前图层最后一个实例的索引,这个索引与批次表及几何体顶点数组中的的batchId一致
|
|
55
|
+
* 注意:该属性是针对图层渲染器设计,未定义相应类型图层渲染器的可以忽略
|
|
56
|
+
* @type {number}
|
|
57
|
+
*/
|
|
58
|
+
this.lastBatchId = -1
|
|
59
|
+
/**
|
|
60
|
+
* 图层渲染器构造绘图命令后,根据 firstBatchId 、 lastBatchId 、几何体顶点数组中的 batchId 计算当前图层的绘制范围,
|
|
61
|
+
* 绘制范围用几何体的起始索引和索引数量表示,对应绘图命令中的offset和count,由于 Cesium 合批构造几何体的结果仍然可能是多个几何体,
|
|
62
|
+
* 所以这里用数组存储起始索引(offset)部分,与合批构造结果一一对应。
|
|
63
|
+
* 注意:该属性是针对图层渲染器设计,未定义相应类型图层渲染器的可以忽略
|
|
64
|
+
*/
|
|
65
|
+
this.offsets = []
|
|
66
|
+
/**
|
|
67
|
+
* 这里用数组存储索引数量(count)部分,与合批构造结果一一对应。详细说明同 offsets 注释
|
|
68
|
+
* 注意:该属性是针对图层渲染器设计,未定义相应类型图层渲染器的可以忽略
|
|
69
|
+
*/
|
|
70
|
+
this.counts = []
|
|
71
|
+
/**
|
|
72
|
+
* 这里用数组存储渲染器分配到图层的绘图命令(DrawCommand)副本,与合批构造结果一一对应。详细说明同 offsets 注释。
|
|
73
|
+
*/
|
|
74
|
+
this.commandList = []
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get id() {
|
|
78
|
+
return this.style.id
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get type() {
|
|
82
|
+
return this.style.type
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 更渲染图层,可在该方法内实现绘图命令构建、动态样式更新等图层渲染相关功能。该方法可以被子类重写或复用,内部从 commandList 属性获取绘图命令(DrawCommand)并加入 frameState.commandList,完成图层渲染对象到Cesium渲染管线的连接
|
|
87
|
+
* @param {Cesium.FrameState} frameState
|
|
88
|
+
* @param {VectorTileset} tileset
|
|
89
|
+
*/
|
|
90
|
+
update(frameState, tileset) {
|
|
91
|
+
const visibility = this.style.layout.getDataConstValue('visibility', this.tile.z)
|
|
92
|
+
if (visibility === 'none') return
|
|
93
|
+
|
|
94
|
+
const commandList = this.commandList
|
|
95
|
+
if (commandList && commandList.length) {
|
|
96
|
+
for (const command of commandList) {
|
|
97
|
+
frameState.commandList.push(command)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 判断对象是否已销毁。基类的 destroy 会自动将该方法改写成返回值为true的版本,子类的 destroy 应通过 super.destory 调用基类的 destroy
|
|
104
|
+
* @returns
|
|
105
|
+
*/
|
|
106
|
+
isDestroyed() {
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 销毁渲染图层,释放资源。基类负责释放通用属性存储的数据,子类的 destroy 应通过 super.destory 调用基类的 destroy
|
|
112
|
+
*/
|
|
113
|
+
destroy() {
|
|
114
|
+
if (this.commandList) {
|
|
115
|
+
this.commandList.length = 0
|
|
116
|
+
}
|
|
117
|
+
if (this.sourceFeatures) {
|
|
118
|
+
this.sourceFeatures.length = 0
|
|
119
|
+
}
|
|
120
|
+
this.style = null
|
|
121
|
+
this.offsets = null
|
|
122
|
+
this.counts = null
|
|
123
|
+
this.tile = null
|
|
124
|
+
this.isDestroyed = function returnTrue() {
|
|
125
|
+
return true
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as MVT from '@mapbox/vector-tile'
|
|
2
|
+
import { StyleLayer } from '../style/StyleLayer'
|
|
3
|
+
import { VectorTileset } from '../VectorTileset'
|
|
4
|
+
import { IRenderLayer } from './IRenderLayer'
|
|
5
|
+
import { registerRenderLayer } from './registerRenderLayer'
|
|
6
|
+
import { VectorTileLOD } from '../VectorTileLOD'
|
|
7
|
+
import { LineLayerVisualizer } from './visualizers/LineLayerVisualizer'
|
|
8
|
+
|
|
9
|
+
export class LineRenderLayer extends IRenderLayer {
|
|
10
|
+
/**
|
|
11
|
+
* @param {MVT.VectorTileFeature[]} sourceFeatures
|
|
12
|
+
* @param {StyleLayer} styleLayer
|
|
13
|
+
* @param {VectorTileLOD} tile
|
|
14
|
+
*/
|
|
15
|
+
constructor(sourceFeatures, styleLayer, tile) {
|
|
16
|
+
super(sourceFeatures, styleLayer, tile)
|
|
17
|
+
this.primitive = null
|
|
18
|
+
this.dasharray = []
|
|
19
|
+
this.dashLength = 0
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
createPrimitve(frameState, tileset) {
|
|
23
|
+
const primitive = new Cesium.PolylineCollection()
|
|
24
|
+
const sourceFeatures = this.sourceFeatures
|
|
25
|
+
const style = this.style
|
|
26
|
+
const tile = this.tile
|
|
27
|
+
|
|
28
|
+
function addPolyline(coordinates, lineWidth, lineColor) {
|
|
29
|
+
if (coordinates.length < 2) return
|
|
30
|
+
|
|
31
|
+
const positions = coordinates.map(coord => Cesium.Cartesian3.fromDegrees(coord[0], coord[1]))
|
|
32
|
+
primitive.add({
|
|
33
|
+
positions,
|
|
34
|
+
width: lineWidth,
|
|
35
|
+
material: Cesium.Material.fromType('Color', {
|
|
36
|
+
color: style.convertColor(lineColor)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const sourceFeature of sourceFeatures) {
|
|
42
|
+
const feature = sourceFeature.toGeoJSON(tile.x, tile.y, tile.z)
|
|
43
|
+
if (!feature.geometry) continue
|
|
44
|
+
|
|
45
|
+
//读取图层样式属性
|
|
46
|
+
const lineWidth = style.paint.getDataValue('line-width', tile.z, sourceFeature)
|
|
47
|
+
const lineColor = style.paint.getDataValue('line-color', tile.z, sourceFeature)
|
|
48
|
+
|
|
49
|
+
const geometryType = feature.geometry.type
|
|
50
|
+
const coordinates = feature.geometry.coordinates
|
|
51
|
+
if (geometryType == 'LineString') {
|
|
52
|
+
addPolyline(coordinates, lineWidth, lineColor)
|
|
53
|
+
}
|
|
54
|
+
else if (geometryType == 'MultiLineString' || geometryType == 'Polygon') {
|
|
55
|
+
for (const ring of coordinates) {
|
|
56
|
+
addPolyline(ring, lineWidth, lineColor)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (geometryType == 'MultiPolygon') {
|
|
60
|
+
for (const polygon of coordinates) {
|
|
61
|
+
for (const ring of polygon) {
|
|
62
|
+
addPolyline(ring, lineWidth, lineColor)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.log('暂不支持几何类型:' + geometryType);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.primitive = primitive
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {Cesium.FrameState} frameState
|
|
76
|
+
* @param {VectorTileset} tileset
|
|
77
|
+
*/
|
|
78
|
+
update(frameState, tileset) {
|
|
79
|
+
// if (!this.primitive) {
|
|
80
|
+
// this.createPrimitve(frameState, tileset)
|
|
81
|
+
// }
|
|
82
|
+
// if (this.primitive && this.primitive.length) {
|
|
83
|
+
// this.primitive.update(frameState)
|
|
84
|
+
// }
|
|
85
|
+
super.update(frameState, tileset)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
destroy() {
|
|
89
|
+
this.primitive = this.primitive && this.primitive.destroy()
|
|
90
|
+
super.destroy()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
registerRenderLayer('line', LineRenderLayer, LineLayerVisualizer)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as MVT from '@mapbox/vector-tile'
|
|
2
|
+
import { StyleLayer } from '../style/StyleLayer'
|
|
3
|
+
import { VectorTileLOD } from '../VectorTileLOD'
|
|
4
|
+
import { IRenderLayer } from './IRenderLayer'
|
|
5
|
+
import { SymbolLayerVisualizer } from './visualizers/SymbolLayerVisualizer'
|
|
6
|
+
import { registerRenderLayer } from './registerRenderLayer'
|
|
7
|
+
|
|
8
|
+
export class SymbolRenderLayer extends IRenderLayer {
|
|
9
|
+
/**
|
|
10
|
+
* @param {MVT.VectorTileFeature[]} sourceFeatures
|
|
11
|
+
* @param {StyleLayer} style
|
|
12
|
+
* @param {VectorTileLOD} tile
|
|
13
|
+
*/
|
|
14
|
+
constructor(sourceFeatures, styleLayer, tile) {
|
|
15
|
+
super(sourceFeatures, styleLayer, tile)
|
|
16
|
+
this.labels = []
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {Cesium.FrameState} frameState
|
|
21
|
+
* @param {VectorTileset} tileset
|
|
22
|
+
*/
|
|
23
|
+
update(frameState, tileset) {
|
|
24
|
+
//TODO:动态更新符号样式
|
|
25
|
+
|
|
26
|
+
super.update(frameState, tileset)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
registerRenderLayer('symbol', SymbolRenderLayer, SymbolLayerVisualizer)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RenderLayers, LayerVisualizers, registerRenderLayer } from "./registerRenderLayer";
|
|
2
|
+
import { ILayerVisualizer } from "./visualizers/ILayerVisualizer";
|
|
3
|
+
import { IRenderLayer } from "./IRenderLayer";
|
|
4
|
+
import { BackgroundRenderLayer } from "./BackgroundRenderLayer";
|
|
5
|
+
import { FillRenderLayer } from "./FillRenderLayer";
|
|
6
|
+
import { LineRenderLayer } from "./LineRenderLayer";
|
|
7
|
+
import {SymbolRenderLayer } from "./SymbolRenderLayer";
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
RenderLayers, LayerVisualizers, registerRenderLayer,
|
|
11
|
+
IRenderLayer, ILayerVisualizer,
|
|
12
|
+
BackgroundRenderLayer,
|
|
13
|
+
FillRenderLayer,
|
|
14
|
+
LineRenderLayer,
|
|
15
|
+
SymbolRenderLayer
|
|
16
|
+
}
|