Cesium 实战 - OD 线,动态连接线
最近有个卫星相关的项目,希望有一个卫星通信的效果,在思考之后,觉得其实就是一个线段 entity 对象,给他一个动态效果应该可以实现。
经尝试之后,在之前的流动线效果基础上进行修改,达到了通信效果。
实际上是通过自定义材质类,通过着色器代码实现。
本文包含OD 线动态效果代码、完整代码以及在线示例三部分。
OD 线动态效果代码
/**
* @description:卫星通信材质
* @date: 2023年6月17日10:43:18
*/
function SatelliteMaterialProperty(options) {
// 默认参数设置
this._definitionChanged = new Cesium.Event();
this.color = options.color;
}
Object.defineProperties(SatelliteMaterialProperty.prototype, {
isConstant: {
get: function() {
return false;
}
},
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
color: Cesium.createPropertyDescriptor('color')
});
SatelliteMaterialProperty.prototype.getType = function(time) {
return 'SatelliteMaterial';
};
SatelliteMaterialProperty.prototype.getValue = function(time, result) {
if (!Cesium.defined(result)) {
result = {
};
}
result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
viewer.scene.requestRender();
return result;
};
SatelliteMaterialProperty.prototype.equals = function(other) {
return this === other ||
(other instanceof SatelliteMaterialProperty &&
Cesium.Property.equals(this._color, other._color));
};
Cesium.Material.SatelliteType = 'SatelliteMaterial';
Cesium.Material.SatelliteSource = `
uniform vec4 color;
uniform float speed;
uniform float percent;
uniform float gradient;
uniform float count;
czm_material czm_getMaterial(czm_materialInput materialInput){
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
float t =fract(czm_frameNumber * speed / 1000.0);
float v = 1.0-(1.0-smoothstep(gradient,0.0,fract(st.x*count-t)))*0.95;
material.diffuse = color.rgb/10.0 + vec3(v)*9.0;
material.alpha = color.a;
return material;
}
`;
Cesium.Material._materialCache.addMaterial(Cesium.Material.SatelliteType, {
fabric: {
type: Cesium.Material.SatelliteType,
uniforms: {
color: new Cesium.Color(1.0, 0.0, 1.0, 0.1),
speed: 30.0,
gradient: 0.2,
count: 15,
},
source: Cesium.Material.SatelliteSource
},
translucent: function(material) {
return true;
}
});
以下是模拟卫星通信效果:
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Use correct character set. -->
<meta charset="utf-8"/>
<!-- Tell IE to use the latest, best version. -->
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
/>
<title>Cesium model video</title>
<link rel="stylesheet" href="./popup.css" type="text/css">
<script src="http://openlayers.vip/examples/csdn/Cesium.js"></script>
<script src="./cesium_init.js"></script>
<script src="http://www.openlayers.vip/examples/resources/jquery-3.5.1.min.js"></script>
<script src="./CesiumPopup.js"></script>
<style>
@import url(./Widgets/widgets.css);
html,
body,
#cesiumContainer {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
</style>
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?f80a36f14f8a73bb0f82e0fdbcee3058";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// 创建三维球
const viewer = init();
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(
111.286419,31.864436,2000000.0
),
model: {
uri: "https://www.openlayers.vip/examples/resources/weixing.gltf",
scale: 60.0,
},
});
viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(
118.286419,31.864436,2000000.0
),
model: {
uri: "https://www.openlayers.vip/examples/resources/weixing.gltf",
scale: 70.0,
color: new Cesium.Color(0.0, 1.0, 1.0, 0.7),
},
});
/**
* @description:卫星通信材质
* @date: 2023年6月17日10:43:18
*/
function SatelliteMaterialProperty(options) {
// 默认参数设置
this._definitionChanged = new Cesium.Event();
this.color = options.color;
}
Object.defineProperties(SatelliteMaterialProperty.prototype, {
isConstant: {
get: function() {
return false;
}
},
definitionChanged: {
get: function() {
return this._definitionChanged;
}
},
color: Cesium.createPropertyDescriptor('color')
});
SatelliteMaterialProperty.prototype.getType = function(time) {
return 'SatelliteMaterial';
};
SatelliteMaterialProperty.prototype.getValue = function(time, result) {
if (!Cesium.defined(result)) {
result = {
};
}
result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
viewer.scene.requestRender();
return result;
};
SatelliteMaterialProperty.prototype.equals = function(other) {
return this === other ||
(other instanceof SatelliteMaterialProperty &&
Cesium.Property.equals(this._color, other._color));
};
Cesium.Material.SatelliteType = 'SatelliteMaterial';
Cesium.Material.SatelliteSource = `
uniform vec4 color;
uniform float speed;
uniform float percent;
uniform float gradient;
uniform float count;
czm_material czm_getMaterial(czm_materialInput materialInput){
czm_material material = czm_getDefaultMaterial(materialInput);
vec2 st = materialInput.st;
float t =fract(czm_frameNumber * speed / 1000.0);
float v = 1.0-(1.0-smoothstep(gradient,0.0,fract(st.x*count-t)))*0.95;
material.diffuse = color.rgb/10.0 + vec3(v)*9.0;
material.alpha = color.a;
return material;
}
`;
Cesium.Material._materialCache.addMaterial(Cesium.Material.SatelliteType, {
fabric: {
type: Cesium.Material.SatelliteType,
uniforms: {
color: new Cesium.Color(1.0, 0.0, 1.0, 0.1),
speed: 30.0,
gradient: 0.2,
count: 15,
},
source: Cesium.Material.SatelliteSource
},
translucent: function(material) {
return true;
}
});
viewer.entities.add({
name: "Blue dashed line",
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
111.286419,31.864436,2000000.0,
118.286419,31.864436,2000000.0
]),
width: 6,
material: new SatelliteMaterialProperty({
color: new Cesium.Color(1.0, 0.0, 0.0, 0.1)
}),
},
});
viewer.zoomTo(viewer.entities);
</script>
</body>
</html>
示例建立了两个卫星,模拟通信效果。