// src/utils/circleRippleMaterialProperty.js
class CircleRippleMaterialProperty {
constructor(options = {}) {
this._definitionChanged = new Cesium.Event();
this._color = Cesium.defaultValue(options.color, Cesium.Color.BLUE);
this._speed = Cesium.defaultValue(options.speed, 3.0);
this._count = Cesium.defaultValue(options.count, 6);
this._gradient = Cesium.defaultValue(options.gradient, 0.1);
// GLSL着色器源码
this._source = `
uniform vec4 color;
uniform float speed;
uniform float count;
uniform float gradient;
czm_material czm_getMaterial(czm_materialInput materialInput) {
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
float time = czm_frameNumber * speed / 1000.0;
float d = distance(st, vec2(0.5, 0.5));
// 多圈波纹效果
float alpha = 0.0;
for(float i = 0.0; i < count; i++) {
// 波纹方程:sin(波纹密度 * d - 时间 * 角频率 - 相位偏移)
float ripple = sin(d * 20.0 - time * 2.0 - i * 0.5);
// 边缘平滑过渡
float fade = smoothstep(0.0, 0.3, d) * (1.0 - smoothstep(0.3, 0.5, d));
// 边缘渐变效果
alpha += abs(ripple) * fade * pow(1.0 - d, gradient * 10.0);
}
material.alpha = alpha * color.a;
// 颜色混合:中心到边缘渐变
material.diffuse = mix(color.rgb, vec3(1.0), d * 0.5);
return material;
}`;
}
get isConstant() { return false; }
get definitionChanged() { return this._definitionChanged; }
get color() { return this._color; }
set color(value) { this._color = value; }
get speed() { return this._speed; }
set speed(value) { this._speed = value; }
get count() { return this._count; }
set count(value) { this._count = value; }
get gradient() { return this._gradient; }
set gradient(value) { this._gradient = value; }
getType() {
return 'CircleRipple';
}
getValue(time, result) {
if (!result) result = {};
result.color = this._color;
result.speed = this._speed;
result.count = this._count;
result.gradient = this._gradient;
return result;
}
equals(other) {
return this === other ||
(other instanceof CircleRippleMaterialProperty &&
Cesium.Color.equals(this._color, other._color) &&
this._speed === other._speed &&
this._count === other._count &&
this._gradient === other._gradient);
}
}
// 注册材质类型到Cesium
Cesium.Material.CircleRippleType = 'CircleRipple';
Cesium.Material._materialCache.addMaterial(Cesium.Material.CircleRippleType, {
fabric: {
type: Cesium.Material.CircleRippleType,
uniforms: {
color: new Cesium.Color(0.0, 0.8, 1.0, 0.6),
speed: 3.0,
count: 6.0,
gradient: 0.1
},
source: new CircleRippleMaterialProperty()._source
},
translucent: function() {
return true;
}
});
export default CircleRippleMaterialProperty;
这个为circleRippleMaterialProperty.js文件,CesiumViewer.vue文件代码如下所示:<!-- src/components/CesiumViewer.vue -->
<template>
<div class="cesium-container">
<div class="title">Cesium动态波纹效果 - 科技蓝</div>
<div id="cesium-container"></div>
<div class="control-panel">
<h3>波纹参数控制</h3>
<div class="slider-container">
<label>波纹速度 <span class="value-display">{{ rippleSpeed.toFixed(1) }}</span></label>
<input type="range" v-model="rippleSpeed" min="0.1" max="10" step="0.1">
</div>
<div class="slider-container">
<label>波纹数量 <span class="value-display">{{ rippleCount }}</span></label>
<input type="range" v-model="rippleCount" min="1" max="12" step="1">
</div>
<div class="slider-container">
<label>波纹大小 <span class="value-display">{{ rippleSize }}</span>米</label>
<input type="range" v-model="rippleSize" min="100" max="2000" step="50">
</div>
<div class="slider-container">
<label>边缘渐变 <span class="value-display">{{ rippleGradient.toFixed(2) }}</span></label>
<input type="range" v-model="rippleGradient" min="0" max="1" step="0.05">
</div>
<div class="coordinates">
<strong>定位坐标:</strong><br>
经度: {{ position.longitude }}<br>
纬度: {{ position.latitude }}
</div>
</div>
</div>
</template>
<script>
import 'cesium/Build/Cesium/Widgets/widgets.css';
import CircleRippleMaterialProperty from '@/utils/circleRippleMaterialProperty';
export default {
name: 'CesiumViewer',
data() {
return {
viewer: null,
rippleEntity: null,
position: {
longitude: 113.194006,
latitude: 27.399411
},
rippleSpeed: 3.0,
rippleCount: 6,
rippleSize: 500,
rippleGradient: 0.1
};
},
watch: {
rippleSpeed(newVal) {
if (this.rippleEntity) {
this.rippleEntity.ellipse.material.speed = newVal;
}
},
rippleCount(newVal) {
if (this.rippleEntity) {
this.rippleEntity.ellipse.material.count = newVal;
}
},
rippleSize(newVal) {
if (this.rippleEntity) {
this.rippleEntity.ellipse.semiMinorAxis = newVal;
this.rippleEntity.ellipse.semiMajorAxis = newVal;
}
},
rippleGradient(newVal) {
if (this.rippleEntity) {
this.rippleEntity.ellipse.material.gradient = newVal;
}
}
},
mounted() {
this.initCesium();
},
beforeDestroy() {
if (this.viewer && !this.viewer.isDestroyed()) {
this.viewer.destroy();
}
},
methods: {
initCesium() {
// 初始化Cesium Viewer
this.viewer = new Cesium.Viewer('cesium-container', {
animation: false,
timeline: false,
baseLayerPicker: true,
geocoder: true,
homeButton: true,
sceneModePicker: true,
navigationHelpButton: false,
fullscreenButton: true,
infoBox: false,
terrainProvider: Cesium.createWorldTerrain()
});
// 添加科技蓝波纹效果
const position = Cesium.Cartesian3.fromDegrees(
this.position.longitude,
this.position.latitude
);
this.rippleEntity = this.viewer.entities.add({
name: '科技蓝动态波纹',
position: position,
ellipse: {
semiMinorAxis: this.rippleSize,
semiMajorAxis: this.rippleSize,
height: 0,
material: new CircleRippleMaterialProperty({
color: Cesium.Color.fromCssColorString("#00FFFF").withAlpha(0.6),
speed: this.rippleSpeed,
count: this.rippleCount,
gradient: this.rippleGradient
})
}
});
// 添加中心点标记
this.viewer.entities.add({
position: position,
point: {
pixelSize: 12,
color: Cesium.Color.fromCssColorString("#FF00FF"),
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2
},
label: {
text: '波纹中心',
font: '14px sans-serif',
fillColor: Cesium.Color.WHITE,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 2,
verticalOrigin: Cesium.VerticalOrigin.TOP,
pixelOffset: new Cesium.Cartesian2(0, -20)
}
});
// 添加坐标点标记
this.viewer.entities.add({
position: position,
label: {
text: `经度: ${this.position.longitude}\n纬度: ${this.position.latitude}`,
font: '12px monospace',
fillColor: Cesium.Color.CYAN,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth: 1,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -50),
backgroundColor: new Cesium.Color(0.1, 0.1, 0.1, 0.7),
padding: new Cesium.Cartesian2(8, 8)
}
});
// 调整相机位置
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(
this.position.longitude,
this.position.latitude,
2000
),
orientation: {
heading: Cesium.Math.toRadians(0),
pitch: Cesium.Math.toRadians(-60),
roll: 0
},
duration: 2.0
});
// 添加科技感背景
this.viewer.scene.backgroundColor = Cesium.Color.fromBytes(10, 20, 40);
this.viewer.scene.globe.baseColor = Cesium.Color.fromBytes(30, 40, 70);
this.viewer.scene.globe.enableLighting = true;
this.viewer.scene.fog.enabled = true;
this.viewer.scene.fog.density = 0.0001;
this.viewer.scene.fog.minimumBrightness = 0.01;
}
}
};
</script>
<style scoped>
.cesium-container {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
#cesium-container {
width: 100%;
height: 100%;
}
.title {
position: absolute;
top: 20px;
left: 20px;
color: #00ffff;
background: rgba(0, 20, 40, 0.7);
padding: 10px 15px;
border-radius: 5px;
z-index: 1000;
font-size: 18px;
text-shadow: 0 0 10px rgba(0, 200, 255, 0.8);
}
.control-panel {
position: absolute;
top: 20px;
right: 20px;
background: rgba(40, 44, 52, 0.8);
padding: 15px;
border-radius: 8px;
color: #61dafb;
z-index: 1000;
box-shadow: 0 0 15px rgba(0, 200, 255, 0.5);
max-width: 280px;
}
.control-panel h3 {
margin-top: 0;
color: #00ffff;
text-align: center;
border-bottom: 1px solid #00aaff;
padding-bottom: 8px;
}
.slider-container {
margin: 12px 0;
}
label {
display: block;
margin-bottom: 5px;
font-size: 14px;
}
input[type="range"] {
width: 100%;
margin: 5px 0;
background: linear-gradient(to right, #0088ff, #00ffff);
height: 6px;
border-radius: 3px;
outline: none;
}
.value-display {
display: inline-block;
width: 40px;
text-align: right;
font-size: 14px;
}
.coordinates {
background: rgba(0, 40, 80, 0.7);
padding: 8px;
border-radius: 4px;
margin-top: 10px;
font-size: 13px;
}
</style>
基于此修改好两个的代码发我
最新发布