前言
之前做淹没分析的时候网上找了很多资料得到的反馈是使用`primitive`时不能动态改变它的`extrudedHeight`
因此就放弃了这种方式采用了不带水波纹的`entity`方式加载(效果比较丑),
今天偶然在网上发现有大佬给出了修改`primitive`属性的方法就立马去实践了一下发现可行
原文链接: https://blog.csdn.net/qq_39142804/article/details/122825831
在这里记录一下加深自己的印象,也贴一下两种实现水面抬高的方法
entity
`entit`y是`Cesium`提供的封装好的api可以通过`CallbackProperty`的方式动态修改`extrudedHeight`方式实现水面抬高的效果代码如下
const boundary = [121.4797, 29.7913, 121.4795, 29.7911, 121.4799, 29.7911, 121.4799, 29.7914]
const riverHeight = 10
const maxHeight = 15
window.viewer.entities.add({
polygon: {
hierarchy: new Cesium.Cartesian3.fromDegreesArray(boundary),
fill: true,
material: new Cesium.Color(255, 255, 255, 0.1) //水面颜色,
extrudedHeight: new Cesium.CallbackProperty(() => {
return riverHeight
}, false),
clampToGround: true,
},
})
setInterval(() => {
riverHeight += 0.25
if (riverHeight >= maxHeight) {
riverHeight = maxHeight
clearInterval(timer)
timer = null
}
}, 500)
primitive
primitive是比较底层的一个api具体就不介绍了(我也不熟)可以看一下官网
cesium.xin/cesium/cn/D…
primitive方式加载水面的方法如下
/**
* 绘制水面
* @param boundary 边界点位 [112.23, 22.25, 112.24, 22.24]
* @param waterImg 水面贴图
* @param extrudedHeight 水面高度
* @returns 水面实例
*/
function useDrawRiver(
boundary: number[],
Cesium: any,
waterImg: any,
extrudedHeight = 18
) {
let riverHeight = extrudedHeight
const polygon = useCreatePolygonGeometry(boundary,riverHeight)
let river = null as any
river = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: polygon,
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
aboveGround: true,
}),
show: true,
asynchronous: false,
releaseGeometryInstances: false,
})
const riverMaterial = new Cesium.Material({
fabric: {
type: 'Water',
uniforms: {
baseWaterColor: new Cesium.Color(64 / 255.0, 157 / 255.0, 253 / 255.0, 0.5), // 水的基本颜色
normalMap: waterImg, // 水的法线贴图
frequency: 500.0, // 水波纹的数量
animationSpeed: 0.05, // 水的流速
amplitude: 5, // 水波纹振幅
specularIntensity: 5, // 镜面反射强度
},
},
})
const scene = window.viewer.scene
river.appearance.material = riverMaterial
scene.primitives.add(river) //添加到场景
river.appearance.material = riverMaterial
return river
}
function useCreatePolygonGeometry(boundary: number[], extrudedHeight: number) {
const polygon = new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(boundary)),
extrudedHeight,
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
})
return polygon
}
修改extrudedHeight高度实现水面抬升效果
这里我们可以利用Object.defineProperty监听extrudedHeight属性然后再去修改河面的状态触发cesium的update方法最后改变extrudedHeight值的时候就可以实现动态高度的效果了
Object.defineProperty(river, 'extrudedHeight', {
get() {
return riverHeight
},
set(newVal) {
if (typeof newVal !== 'number') {
return
}
riverHeight = newVal
river._state = 3 // 重置primitive状态触发cesium update方法
river._appearance = undefined
river.geometryInstances.geometry = useCreatePolygonGeometry(boundary, riverHeight)
},
})
代码合并
/**
* 绘制水面
* @param boundary 边界点位 [112.23, 22.25, 112.24, 22.24]
* @param waterImg 水面贴图
* @param extrudedHeight 水面高度
* @returns 水面实例
*/
function useDrawRiver(
boundary: number[],
Cesium: any,
waterImg: any,
extrudedHeight = 18
) {
let riverHeight = extrudedHeight
const polygon = useCreatePolygonGeometry(boundary,riverHeight)
let river = null as any
river = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: polygon,
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
aboveGround: true,
}),
show: true,
asynchronous: false,
releaseGeometryInstances: false,
})
const riverMaterial = new Cesium.Material({
fabric: {
type: 'Water',
uniforms: {
baseWaterColor: new Cesium.Color(64 / 255.0, 157 / 255.0, 253 / 255.0, 0.5), // 水的基本颜色
normalMap: waterImg, // 水的法线贴图
frequency: 500.0, // 水波纹的数量
animationSpeed: 0.05, // 水的流速
amplitude: 5, // 水波纹振幅
specularIntensity: 5, // 镜面反射强度
},
},
})
const scene = window.viewer.scene
river.appearance.material = riverMaterial
scene.primitives.add(river) //添加到场景
river.appearance.material = riverMaterial
Object.defineProperty(river, 'extrudedHeight', {
get() {
return riverHeight
},
set(newVal) {
if (typeof newVal !== 'number') {
return
}
riverHeight = newVal
river._state = 3 // 重置primitive状态触发cesium update方法
river._appearance = undefined
river.geometryInstances.geometry = useCreatePolygonGeometry(boundary, riverHeight)
},
})
return river
}
function useCreatePolygonGeometry(boundary: number[], extrudedHeight: number) {
const polygon = new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(boundary)),
extrudedHeight,
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
})
return polygon
}
调用
let river = useDrawRiver( boundary //多边形点位,Cesium,waterImg//水面纹理)
timer = setInterval(() => {
riverHeight += 0.25
rver.extrudedHeight = riverHeight
if (riverHeight >= maxHeight) {
riverHeight = maxHeight
// 清除定时器
}
}, 500)