Cesium实战用CallbackProperty实现动态扩散圆效果附完整代码与避坑指南1. 动态扩散圆效果的技术实现原理动态扩散圆效果在三维GIS项目中常用于模拟雷达扫描、污染扩散等场景。其核心实现原理是通过Cesium的CallbackProperty机制动态更新圆的半径和材质属性。1.1 CallbackProperty工作机制CallbackProperty是Cesium的核心特性之一它允许我们通过回调函数动态计算实体属性值new Cesium.CallbackProperty(callbackFunction, isConstant)callbackFunction: 每次渲染帧时调用的函数isConstant: 表示属性值是否恒定的布尔值1.2 动态半径实现通过不断修改圆的半长轴和半短轴实现扩散效果let currentRadius minRadius; function updateRadius() { currentRadius stepSize; if(currentRadius maxRadius) { currentRadius minRadius; } return currentRadius; } ellipse.semiMajorAxis new Cesium.CallbackProperty(updateRadius, false); ellipse.semiMinorAxis new Cesium.CallbackProperty(updateRadius, false);1.3 动态材质实现结合透明度变化实现渐隐效果function updateColor() { const alpha 1 - (currentRadius / maxRadius); return Cesium.Color.WHITE.withAlpha(alpha); } ellipse.material new Cesium.ColorMaterialProperty( new Cesium.CallbackProperty(updateColor, false) );2. 两种材质方案对比2.1 纯色材质方案特性优点缺点实现难度简单效果单一性能消耗低视觉效果不够丰富适用场景简单扩散效果需要复杂纹理时不足material: new Cesium.ColorMaterialProperty( new Cesium.CallbackProperty(updateColor, false) )2.2 图片纹理方案特性优点缺点视觉效果丰富可定制实现复杂度高性能影响中等需要处理图片资源适用场景需要特殊纹理效果简单场景可能过度设计material: new Cesium.ImageMaterialProperty({ image: path/to/texture.png, repeat: new Cesium.Cartesian2(1.0, 1.0), transparent: true, color: new Cesium.CallbackProperty(updateColor, false) })提示图片纹理方案中建议使用PNG格式的环形纹理图并开启透明通道以获得最佳效果。3. 完整实现代码与封装3.1 基础实现代码// 基本参数配置 const config { minRadius: 4000, maxRadius: 400000, stepSize: 4000, center: Cesium.Cartesian3.fromDegrees(122.0, 23.0), outlineColor: Cesium.Color.RED }; let currentRadius config.minRadius; // 半径更新函数 function updateRadius() { currentRadius config.stepSize; if(currentRadius config.maxRadius) { currentRadius config.minRadius; } return currentRadius; } // 颜色更新函数 function updateColor() { const alpha 1 - (currentRadius / config.maxRadius); return Cesium.Color.WHITE.withAlpha(alpha); } // 创建动态圆实体 const dynamicCircle viewer.entities.add({ position: config.center, ellipse: { semiMinorAxis: new Cesium.CallbackProperty(updateRadius, false), semiMajorAxis: new Cesium.CallbackProperty(updateRadius, false), material: new Cesium.ColorMaterialProperty( new Cesium.CallbackProperty(updateColor, false) ), outlineColor: config.outlineColor } });3.2 可复用组件封装/** * 动态扩散圆组件 * class DynamicRange */ export default class DynamicRange { /** * 构造函数 * param {Object} options - 配置选项 * param {Cesium.Viewer} options.viewer - Cesium Viewer实例 */ constructor(options) { this.viewer options.viewer; this._entities []; } /** * 创建基于图片纹理的动态扩散圆 * param {Object} options - 配置选项 * param {number} options.minR - 最小半径 * param {number} options.maxR - 最大半径 * param {number} options.deviationR - 每次增加的半径值 * param {Cesium.Cartesian3} options.position - 圆心位置 * param {string} options.imageUrl - 纹理图片路径 * returns {Cesium.Entity} 创建的实体对象 */ createTexturedCircle(options) { let currentR options.minR; function updateRadius() { currentR options.deviationR; if(currentR options.maxR) currentR options.minR; return currentR; } function updateColor() { const alpha 1 - (currentR / options.maxR); return Cesium.Color.WHITE.withAlpha(alpha); } const entity this.viewer.entities.add({ position: options.position, ellipse: { semiMinorAxis: new Cesium.CallbackProperty(updateRadius, false), semiMajorAxis: new Cesium.CallbackProperty(updateRadius, false), material: new Cesium.ImageMaterialProperty({ image: options.imageUrl, repeat: new Cesium.Cartesian2(1.0, 1.0), transparent: true, color: new Cesium.CallbackProperty(updateColor, false) }), outlineColor: Cesium.Color.RED } }); this._entities.push(entity); return entity; } /** * 创建基于纯色材质的动态扩散圆 * param {Object} options - 配置选项 * param {number} options.minR - 最小半径 * param {number} options.maxR - 最大半径 * param {number} options.deviationR - 每次增加的半径值 * param {Cesium.Cartesian3} options.position - 圆心位置 * param {Cesium.Color} options.baseColor - 基础颜色 * returns {Cesium.Entity} 创建的实体对象 */ createSolidColorCircle(options) { let currentR options.minR; function updateRadius() { currentR options.deviationR; if(currentR options.maxR) currentR options.minR; return currentR; } function updateColor() { const alpha 1 - (currentR / options.maxR); return options.baseColor.withAlpha(alpha); } const entity this.viewer.entities.add({ position: options.position, ellipse: { semiMinorAxis: new Cesium.CallbackProperty(updateRadius, false), semiMajorAxis: new Cesium.CallbackProperty(updateRadius, false), material: new Cesium.ColorMaterialProperty( new Cesium.CallbackProperty(updateColor, false) ), outlineColor: options.outlineColor || Cesium.Color.RED } }); this._entities.push(entity); return entity; } /** * 移除所有创建的动态圆实体 */ removeAll() { this._entities.forEach(entity { this.viewer.entities.remove(entity); }); this._entities []; } }4. 性能优化与常见问题解决4.1 性能优化技巧合理设置回调频率对于不需要每帧更新的属性可以设置isConstant为true使用节流技术控制更新频率纹理优化// 预加载纹理图片 const texture new Image(); texture.src path/to/texture.png; texture.onload () { // 纹理加载完成后再创建实体 };实例化多个扩散圆时共享相同的CallbackProperty实例使用EntityCollection批量管理实体4.2 常见问题及解决方案问题1扩散效果不流畅原因deviationR设置过大或帧率不足解决方案减小deviationR值使用requestAnimationFrame控制更新节奏检查浏览器性能分析器问题2纹理显示异常// 正确的纹理加载方式 material: new Cesium.ImageMaterialProperty({ image: new Cesium.Resource({ url: path/to/texture.png, retryAttempts: 3 // 添加重试机制 }), // 其他配置... })问题3内存泄漏// 在移除实体时确保释放资源 viewer.entities.remove(entity); // 对于自定义材质手动释放纹理资源 if(entity.ellipse.material.image) { entity.ellipse.material.image.destroy(); }5. 实际应用案例5.1 雷达扫描效果实现const radar new DynamicRange({ viewer: viewer }); // 创建3个不同速度的雷达扫描圈 radar.createTexturedCircle({ minR: 1000, maxR: 50000, deviationR: 80, position: Cesium.Cartesian3.fromDegrees(121.5, 25.0), imageUrl: assets/radar_texture.png }); radar.createTexturedCircle({ minR: 1000, maxR: 50000, deviationR: 120, position: Cesium.Cartesian3.fromDegrees(121.5, 25.0), imageUrl: assets/radar_texture.png }); radar.createTexturedCircle({ minR: 1000, maxR: 50000, deviationR: 200, position: Cesium.Cartesian3.fromDegrees(121.5, 25.0), imageUrl: assets/radar_texture.png });5.2 污染扩散模拟const pollutionSimulator new DynamicRange({ viewer: viewer }); // 创建污染源扩散效果 const pollutionSource pollutionSimulator.createSolidColorCircle({ minR: 500, maxR: 20000, deviationR: 50, position: Cesium.Cartesian3.fromDegrees(120.8, 24.3), baseColor: Cesium.Color.GREEN, outlineColor: Cesium.Color.DARKGREEN }); // 添加随时间变化的污染浓度 let concentration 0; setInterval(() { concentration (concentration 0.1) % 1; pollutionSource.ellipse.material.color.getValue().alpha concentration * 0.7; }, 1000);6. 扩展与进阶6.1 动态参数调整// 创建可调节参数的扩散圆 const configurableCircle { params: { minR: 1000, maxR: 30000, deviationR: 100, color: Cesium.Color.BLUE } }; const circleEntity dynamicRange.createSolidColorCircle(configurableCircle.params); // 添加GUI控制 const gui new dat.GUI(); gui.add(configurableCircle.params, minR, 500, 5000).onChange(updateCircle); gui.add(configurableCircle.params, maxR, 10000, 100000).onChange(updateCircle); gui.add(configurableCircle.params, deviationR, 10, 500).onChange(updateCircle); function updateCircle() { viewer.entities.remove(circleEntity); circleEntity dynamicRange.createSolidColorCircle(configurableCircle.params); }6.2 结合其他Cesium特性// 结合地形高度调整 function getHeightAdjustedPosition(longitude, latitude, height) { const position Cesium.Cartesian3.fromDegrees(longitude, latitude); const cartographic Cesium.Cartographic.fromCartesian(position); cartographic.height height; return Cesium.Cartographic.toCartesian(cartographic); } // 创建跟随地形高度的扩散圆 dynamicRange.createTexturedCircle({ minR: 2000, maxR: 40000, deviationR: 150, position: getHeightAdjustedPosition(121.0, 23.5, 1000), imageUrl: assets/ring_texture.png });在实际项目中我发现动态扩散圆效果的性能很大程度上取决于回调函数的复杂度和同时存在的动态实体数量。通过合理的参数调优和资源管理可以在保证视觉效果的同时维持良好的渲染性能。
Cesium实战:用CallbackProperty实现动态扩散圆效果(附完整代码与避坑指南)
发布时间:2026/5/19 6:26:30
Cesium实战用CallbackProperty实现动态扩散圆效果附完整代码与避坑指南1. 动态扩散圆效果的技术实现原理动态扩散圆效果在三维GIS项目中常用于模拟雷达扫描、污染扩散等场景。其核心实现原理是通过Cesium的CallbackProperty机制动态更新圆的半径和材质属性。1.1 CallbackProperty工作机制CallbackProperty是Cesium的核心特性之一它允许我们通过回调函数动态计算实体属性值new Cesium.CallbackProperty(callbackFunction, isConstant)callbackFunction: 每次渲染帧时调用的函数isConstant: 表示属性值是否恒定的布尔值1.2 动态半径实现通过不断修改圆的半长轴和半短轴实现扩散效果let currentRadius minRadius; function updateRadius() { currentRadius stepSize; if(currentRadius maxRadius) { currentRadius minRadius; } return currentRadius; } ellipse.semiMajorAxis new Cesium.CallbackProperty(updateRadius, false); ellipse.semiMinorAxis new Cesium.CallbackProperty(updateRadius, false);1.3 动态材质实现结合透明度变化实现渐隐效果function updateColor() { const alpha 1 - (currentRadius / maxRadius); return Cesium.Color.WHITE.withAlpha(alpha); } ellipse.material new Cesium.ColorMaterialProperty( new Cesium.CallbackProperty(updateColor, false) );2. 两种材质方案对比2.1 纯色材质方案特性优点缺点实现难度简单效果单一性能消耗低视觉效果不够丰富适用场景简单扩散效果需要复杂纹理时不足material: new Cesium.ColorMaterialProperty( new Cesium.CallbackProperty(updateColor, false) )2.2 图片纹理方案特性优点缺点视觉效果丰富可定制实现复杂度高性能影响中等需要处理图片资源适用场景需要特殊纹理效果简单场景可能过度设计material: new Cesium.ImageMaterialProperty({ image: path/to/texture.png, repeat: new Cesium.Cartesian2(1.0, 1.0), transparent: true, color: new Cesium.CallbackProperty(updateColor, false) })提示图片纹理方案中建议使用PNG格式的环形纹理图并开启透明通道以获得最佳效果。3. 完整实现代码与封装3.1 基础实现代码// 基本参数配置 const config { minRadius: 4000, maxRadius: 400000, stepSize: 4000, center: Cesium.Cartesian3.fromDegrees(122.0, 23.0), outlineColor: Cesium.Color.RED }; let currentRadius config.minRadius; // 半径更新函数 function updateRadius() { currentRadius config.stepSize; if(currentRadius config.maxRadius) { currentRadius config.minRadius; } return currentRadius; } // 颜色更新函数 function updateColor() { const alpha 1 - (currentRadius / config.maxRadius); return Cesium.Color.WHITE.withAlpha(alpha); } // 创建动态圆实体 const dynamicCircle viewer.entities.add({ position: config.center, ellipse: { semiMinorAxis: new Cesium.CallbackProperty(updateRadius, false), semiMajorAxis: new Cesium.CallbackProperty(updateRadius, false), material: new Cesium.ColorMaterialProperty( new Cesium.CallbackProperty(updateColor, false) ), outlineColor: config.outlineColor } });3.2 可复用组件封装/** * 动态扩散圆组件 * class DynamicRange */ export default class DynamicRange { /** * 构造函数 * param {Object} options - 配置选项 * param {Cesium.Viewer} options.viewer - Cesium Viewer实例 */ constructor(options) { this.viewer options.viewer; this._entities []; } /** * 创建基于图片纹理的动态扩散圆 * param {Object} options - 配置选项 * param {number} options.minR - 最小半径 * param {number} options.maxR - 最大半径 * param {number} options.deviationR - 每次增加的半径值 * param {Cesium.Cartesian3} options.position - 圆心位置 * param {string} options.imageUrl - 纹理图片路径 * returns {Cesium.Entity} 创建的实体对象 */ createTexturedCircle(options) { let currentR options.minR; function updateRadius() { currentR options.deviationR; if(currentR options.maxR) currentR options.minR; return currentR; } function updateColor() { const alpha 1 - (currentR / options.maxR); return Cesium.Color.WHITE.withAlpha(alpha); } const entity this.viewer.entities.add({ position: options.position, ellipse: { semiMinorAxis: new Cesium.CallbackProperty(updateRadius, false), semiMajorAxis: new Cesium.CallbackProperty(updateRadius, false), material: new Cesium.ImageMaterialProperty({ image: options.imageUrl, repeat: new Cesium.Cartesian2(1.0, 1.0), transparent: true, color: new Cesium.CallbackProperty(updateColor, false) }), outlineColor: Cesium.Color.RED } }); this._entities.push(entity); return entity; } /** * 创建基于纯色材质的动态扩散圆 * param {Object} options - 配置选项 * param {number} options.minR - 最小半径 * param {number} options.maxR - 最大半径 * param {number} options.deviationR - 每次增加的半径值 * param {Cesium.Cartesian3} options.position - 圆心位置 * param {Cesium.Color} options.baseColor - 基础颜色 * returns {Cesium.Entity} 创建的实体对象 */ createSolidColorCircle(options) { let currentR options.minR; function updateRadius() { currentR options.deviationR; if(currentR options.maxR) currentR options.minR; return currentR; } function updateColor() { const alpha 1 - (currentR / options.maxR); return options.baseColor.withAlpha(alpha); } const entity this.viewer.entities.add({ position: options.position, ellipse: { semiMinorAxis: new Cesium.CallbackProperty(updateRadius, false), semiMajorAxis: new Cesium.CallbackProperty(updateRadius, false), material: new Cesium.ColorMaterialProperty( new Cesium.CallbackProperty(updateColor, false) ), outlineColor: options.outlineColor || Cesium.Color.RED } }); this._entities.push(entity); return entity; } /** * 移除所有创建的动态圆实体 */ removeAll() { this._entities.forEach(entity { this.viewer.entities.remove(entity); }); this._entities []; } }4. 性能优化与常见问题解决4.1 性能优化技巧合理设置回调频率对于不需要每帧更新的属性可以设置isConstant为true使用节流技术控制更新频率纹理优化// 预加载纹理图片 const texture new Image(); texture.src path/to/texture.png; texture.onload () { // 纹理加载完成后再创建实体 };实例化多个扩散圆时共享相同的CallbackProperty实例使用EntityCollection批量管理实体4.2 常见问题及解决方案问题1扩散效果不流畅原因deviationR设置过大或帧率不足解决方案减小deviationR值使用requestAnimationFrame控制更新节奏检查浏览器性能分析器问题2纹理显示异常// 正确的纹理加载方式 material: new Cesium.ImageMaterialProperty({ image: new Cesium.Resource({ url: path/to/texture.png, retryAttempts: 3 // 添加重试机制 }), // 其他配置... })问题3内存泄漏// 在移除实体时确保释放资源 viewer.entities.remove(entity); // 对于自定义材质手动释放纹理资源 if(entity.ellipse.material.image) { entity.ellipse.material.image.destroy(); }5. 实际应用案例5.1 雷达扫描效果实现const radar new DynamicRange({ viewer: viewer }); // 创建3个不同速度的雷达扫描圈 radar.createTexturedCircle({ minR: 1000, maxR: 50000, deviationR: 80, position: Cesium.Cartesian3.fromDegrees(121.5, 25.0), imageUrl: assets/radar_texture.png }); radar.createTexturedCircle({ minR: 1000, maxR: 50000, deviationR: 120, position: Cesium.Cartesian3.fromDegrees(121.5, 25.0), imageUrl: assets/radar_texture.png }); radar.createTexturedCircle({ minR: 1000, maxR: 50000, deviationR: 200, position: Cesium.Cartesian3.fromDegrees(121.5, 25.0), imageUrl: assets/radar_texture.png });5.2 污染扩散模拟const pollutionSimulator new DynamicRange({ viewer: viewer }); // 创建污染源扩散效果 const pollutionSource pollutionSimulator.createSolidColorCircle({ minR: 500, maxR: 20000, deviationR: 50, position: Cesium.Cartesian3.fromDegrees(120.8, 24.3), baseColor: Cesium.Color.GREEN, outlineColor: Cesium.Color.DARKGREEN }); // 添加随时间变化的污染浓度 let concentration 0; setInterval(() { concentration (concentration 0.1) % 1; pollutionSource.ellipse.material.color.getValue().alpha concentration * 0.7; }, 1000);6. 扩展与进阶6.1 动态参数调整// 创建可调节参数的扩散圆 const configurableCircle { params: { minR: 1000, maxR: 30000, deviationR: 100, color: Cesium.Color.BLUE } }; const circleEntity dynamicRange.createSolidColorCircle(configurableCircle.params); // 添加GUI控制 const gui new dat.GUI(); gui.add(configurableCircle.params, minR, 500, 5000).onChange(updateCircle); gui.add(configurableCircle.params, maxR, 10000, 100000).onChange(updateCircle); gui.add(configurableCircle.params, deviationR, 10, 500).onChange(updateCircle); function updateCircle() { viewer.entities.remove(circleEntity); circleEntity dynamicRange.createSolidColorCircle(configurableCircle.params); }6.2 结合其他Cesium特性// 结合地形高度调整 function getHeightAdjustedPosition(longitude, latitude, height) { const position Cesium.Cartesian3.fromDegrees(longitude, latitude); const cartographic Cesium.Cartographic.fromCartesian(position); cartographic.height height; return Cesium.Cartographic.toCartesian(cartographic); } // 创建跟随地形高度的扩散圆 dynamicRange.createTexturedCircle({ minR: 2000, maxR: 40000, deviationR: 150, position: getHeightAdjustedPosition(121.0, 23.5, 1000), imageUrl: assets/ring_texture.png });在实际项目中我发现动态扩散圆效果的性能很大程度上取决于回调函数的复杂度和同时存在的动态实体数量。通过合理的参数调优和资源管理可以在保证视觉效果的同时维持良好的渲染性能。