本人小白一枚,文章如有问题还请各位大神评论区指出。整体实现是参考SuperMap iClient3D for Cesium的淹没分析功能源码~
文章目录
前言
SuperMap iClient3D for Cesium提供了淹没分析的方法——FloodAnalysis3D,但是本文主要是采用DrawHandler绘制方法类结合setInterval定时器实现淹没动画,为了显示效果更加美观,代码还采用了HypsometricSetting分层设色类,实现根据地理高程实现不同颜色的过度渲染效果。
一、主要功能
效果图:
通过设置淹没分析的起始高度、最大淹没高度、淹没速度三个参数,然后绘制淹没区域即可实现淹没分析的动画效果。
二、具体实现
1.HTML主要结构
<div class="btnBox">
<span
><p>起始高度(米):</p>
<el-input size="small" v-model="minHeight"
/></span>
<span
><p>最大高度(米):</p>
<el-input size="small" v-model="maxHeight"
/></span>
<span
><p>淹没速度(米/秒):</p>
<el-input size="small" v-model="speed"
/></span>
<el-button type="primary" @click="begin">开 始</el-button>
<el-button type="primary" @click="clear">清 除</el-button>
</div>
2.javascript
代码如下:
<script setup>
import { ref, onBeforeUnmount } from "vue";
import { useStore } from "vuex";
const store = useStore();
let minHeight = ref(300);
let maxHeight = ref(9000);
let speed = ref(500);
// 初始化数据
var interval = null; //定时器
var scene = viewer.scene;
let hypFlood;
function init() {
hypFlood = new Cesium.HypsometricSetting(); //分层设色类。
let floodColorTable = new Cesium.ColorTable();
colorTableInit(floodColorTable);
hypFlood.DisplayMode = Cesium.HypsometricSettingEnum.DisplayMode.FACE; //获取或设置显示模式
hypFlood._lineColor = new Cesium.Color(1.0, 0.0, 0.0, 1.0);
hypFlood.MinVisibleValue = 0; //获取或设置最小可见值
hypFlood.MaxVisibleValue = 0;
hypFlood.ColorTableMinKey = 1; //获取颜色表的最小key值。
hypFlood.ColorTableMaxKey = 9000;
hypFlood.ColorTable = floodColorTable; //获取或设置颜色表。
hypFlood.Opacity = 0.8; //获取或设置不透明度
hypFlood.LineInterval = 200.0; //获取或设置等值线的间隔。
}
init();
// 默认设置淹没分析颜色
function colorTableInit(floodColorTable) {
floodColorTable.insert(
//颜色表插入新的项。
9000,
new Cesium.Color(210 / 255, 15 / 255, 15 / 255)
);
floodColorTable.insert(6000, new Cesium.Color(221 / 255, 224 / 255, 7 / 255));
floodColorTable.insert(5000, new Cesium.Color(20 / 255, 187 / 255, 18 / 255));
floodColorTable.insert(4000, new Cesium.Color(0, 161 / 255, 1));
floodColorTable.insert(0, new Cesium.Color(9 / 255, 9 / 255, 212 / 255));
}
//绘制多边形
var polygonHandler = new Cesium.DrawHandler(viewer, Cesium.DrawMode.Polygon);
polygonHandler.drawEvt.addEventListener(function (polygon) {
polygonHandler.polygon.show = false;
polygonHandler.polyline.show = false;
var array = [].concat(polygon.object.positions);
let positions = [];
for (var i = 0, len = array.length; i < len; i++) {
var cartographic = Cesium.Cartographic.fromCartesian(array[i]);
var longitude = Cesium.Math.toDegrees(cartographic.longitude);
var latitude = Cesium.Math.toDegrees(cartographic.latitude);
var h = cartographic.height;
if (
positions.indexOf(longitude) == -1 &&
positions.indexOf(latitude) == -1
) {
positions.push(longitude);
positions.push(latitude);
positions.push(h);
}
}
floodUpdate(positions);
polygonHandler.deactivate();
});
// 更新淹没分析
function floodUpdate(positions) {
hypFlood.CoverageArea = positions; //获取或设置分层设色的区域。
let maxValue = parseInt(maxHeight.value);
let minValue = parseInt(minHeight.value);
let currentHeight = minValue;
hypFlood.MinVisibleValue = minValue;
interval = self.setInterval("flood()", 100);
currentHeight = minValue;
window.flood = () => {
if (currentHeight > maxValue) {
self.clearInterval(interval);
return;
}
hypFlood.MaxVisibleValue = currentHeight;
viewer.scene.globe.HypsometricSetting = {
hypsometricSetting: hypFlood,
analysisMode: Cesium.HypsometricSettingEnum.AnalysisRegionMode.ARM_REGION,
};
currentHeight += parseInt(speed.value) / 10;
};
}
// 激活绘制
function begin() {
clear();
polygonHandler.activate();
}
// 清除
function clear() {
self.clearInterval(interval);
polygonHandler.deactivate();
polygonHandler.clear();
viewer.scene.globe.HypsometricSetting = undefined;
}
onBeforeUnmount(() => {
clear();
});
if (!scene.pickPositionSupported) {
alert("不支持深度拾取,淹没分析功能无法使用(无法交互绘制面)!");
}
</script>