vue+cesium示例:坡向分析(附源码下载)
基于cesium和vue实现坡向分析效果,适合学习Cesium与前端框架结合开发3D可视化项目。
demo源码运行环境以及配置
运行环境:依赖Node安装环境,demo本地Node版本:推荐v18+。
运行工具:vscode或者其他工具。
配置方式:下载demo源码,vscode打开,然后顺序执行以下命令:
(1)下载demo环境依赖包命令:npm install
(2)启动demo命令:npm run dev
(3)打包demo命令: npm run build
技术栈
Vue 3.5.13
Vite 6.2.0
Cesium 1.128.0
示例效果

核心源码
<template><divid="cesiumContainer"class="cesium-container"></div></template><scriptsetup>import { onMounted, onUnmounted, ref } from 'vue';import * as Cesium from 'cesium';Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxZjhjYjhkYS1jMzA1LTQ1MTEtYWE1Mi0zODc5NDljOGVkMDYiLCJpZCI6MTAzNjEsInNjb3BlcyI6WyJhc2wiLCJhc3IiLCJhc3ciLCJnYyJdLCJpYXQiOjE1NzA2MDY5ODV9.X7tj92tunUvx6PkDpj3LFsMVBs_SBYyKbIL_G9xKESA';// 声明Cesium Viewer实例let viewer = null;// 组件挂载后初始化CesiumonMounted(async () => {initMap();});const initMap = async () => {// 初始化Cesium Viewerviewer = new Cesium.Viewer('cesiumContainer', {// 基础配置animation: false, // 动画小部件baseLayerPicker: false, // 底图选择器fullscreenButton: false, // 全屏按钮vrButton: false, // VR按钮geocoder: false, // 地理编码搜索框homeButton: false, // 主页按钮infoBox: false, // 信息框 - 禁用点击弹窗sceneModePicker: false, // 场景模式选择器selectionIndicator: false, // 选择指示器timeline: false, // 时间轴navigationHelpButton: false, // 导航帮助按钮navigationInstructionsInitiallyVisible: false, // 导航说明初始可见性scene3DOnly: false, // 仅3D场景// terrain: Cesium.Terrain.fromWorldTerrain(), // 使用世界地形});// 隐藏logoviewer.cesiumWidget.creditContainer.style.display = "none";viewer.scene.globe.enableLighting = false;// 禁用大气层和太阳viewer.scene.skyAtmosphere.show = false;//前提先把场景上的图层全部移除或者隐藏// viewer.scene.globe.baseColor = Cesium.Color.BLACK; //修改地图蓝色背景viewer.scene.globe.baseColor = new Cesium.Color(0.0, 0.1, 0.2, 1.0); //修改地图为暗蓝色背景// 设置抗锯齿viewer.scene.postProcessStages.fxaa.enabled = true;// 清除默认底图viewer.imageryLayers.remove(viewer.imageryLayers.get(0));// 加载底图 - 使用更暗的地图服务const imageryProvider = await Cesium.ArcGisMapServerImageryProvider.fromUrl("https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer");viewer.imageryLayers.addImageryProvider(imageryProvider);viewer.scene.debugShowFramesPerSecond = true;viewer.scene.globe.depthTestAgainstTerrain = true;// viewer.terrainProvider = new Cesium.CesiumTerrainProvider({// url: '//data.mars3d.cn/terrain'// });const terrainProvider = await Cesium.CesiumTerrainProvider.fromIonAssetId(3956);viewer.terrainProvider = terrainProvider;viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(114.20597076416016,31.15141366186558, 5000.0)});//坡向分析class falling {constructor(viewer, config) {this.viewer = viewer;this.config = config;this.loadResult();}loadResult() {let _this = this;const startx1 = _this.config.positons[0];const starty1 = _this.config.positons[1];const startx2 = _this.config.positons[2];const starty2 = _this.config.positons[3];const startx3 = _this.config.positons[4];const starty3 = _this.config.positons[5];const startx4 = _this.config.positons[6];const starty4 = _this.config.positons[7];//坡向显示function analysis(startx1, starty1, startz1, startx2, starty2, startz2, startx3, starty3, startz3, startx4, starty4, startz4) {//高度z全为0const count = 100;let slopelineposition = [];let hireacys = [];let hireacysdistance = []for (let j = 0; j < 100; j++) {for (let i = 0; i < 100; i++) {let hireacy = [];//分割成小面,切分经纬度hireacy.push(new Cesium.Cartesian3(startx1 + (startx2 - startx1) / count * i + (startx4 + (startx3 - startx4) / count * (i) - startx1 - (startx2 - startx1) / count * i) / count * j,starty1 + (starty2 - starty1) / count * i + (starty4 + (starty3 - starty4) / count * (i) - starty1 - (starty2 - starty1) / count * i) / count * j,startz1 + (startz2 - startz1) / count * i + (startz4 + (startz3 - startz4) / count * (i) - startz1 - (startz2 - startz1) / count * i) / count * j))hireacy.push(new Cesium.Cartesian3(startx1 + (startx2 - startx1) / count * (i + 1) + (startx4 + (startx3 - startx4) / count * (i + 1) - startx1 - (startx2 - startx1) / count * (i + 1)) / count * j,starty1 + (starty2 - starty1) / count * (i + 1) + (starty4 + (starty3 - starty4) / count * (i + 1) - starty1 - (starty2 - starty1) / count * (i + 1)) / count * j,startz1 + (startz2 - startz1) / count * (i + 1) + (startz4 + (startz3 - startz4) / count * (i + 1) - startz1 - (startz2 - startz1) / count * (i + 1)) / count * j))hireacy.push(new Cesium.Cartesian3(startx4 + (startx3 - startx4) / count * (i + 1) - (startx4 + (startx3 - startx4) / count * (i + 1) - startx1 - (startx2 - startx1) / count * (i + 1)) / count * (count - 1 - j),starty4 + (starty3 - starty4) / count * (i + 1) - (starty4 + (starty3 - starty4) / count * (i + 1) - starty1 - (starty2 - starty1) / count * (i + 1)) / count * (count - 1 - j),startz4 + (startz3 - startz4) / count * (i + 1) - (startz4 + (startz3 - startz4) / count * (i + 1) - startz1 - (startz2 - startz1) / count * (i + 1)) / count * (count - 1 - j)))hireacy.push(new Cesium.Cartesian3(startx4 + (startx3 - startx4) / count * i - (startx4 + (startx3 - startx4) / count * (i) - startx1 - (startx2 - startx1) / count * i) / count * (count - 1 - j),starty4 + (starty3 - starty4) / count * i - (starty4 + (starty3 - starty4) / count * (i) - starty1 - (starty2 - starty1) / count * i) / count * (count - 1 - j),startz4 + (startz3 - startz4) / count * i - (startz4 + (startz3 - startz4) / count * (i) - startz1 - (startz2 - startz1) / count * i) / count * (count - 1 - j)))hireacys.push(hireacy);//取出面的8个点坐标,拿点坐标去求高度值slopelineposition.push(Cesium.Cartographic.fromDegrees(hireacy[0].x, hireacy[0].y));slopelineposition.push(Cesium.Cartographic.fromDegrees((hireacy[0].x + hireacy[1].x) / 2, (hireacy[0].y + hireacy[1].y) / 2));slopelineposition.push(Cesium.Cartographic.fromDegrees(hireacy[1].x, hireacy[1].y));slopelineposition.push(Cesium.Cartographic.fromDegrees((hireacy[1].x + hireacy[2].x) / 2, (hireacy[1].y + hireacy[2].y) / 2));slopelineposition.push(Cesium.Cartographic.fromDegrees(hireacy[2].x, hireacy[2].y));slopelineposition.push(Cesium.Cartographic.fromDegrees((hireacy[2].x + hireacy[3].x) / 2, (hireacy[2].y + hireacy[3].y) / 2));slopelineposition.push(Cesium.Cartographic.fromDegrees(hireacy[3].x, hireacy[3].y));slopelineposition.push(Cesium.Cartographic.fromDegrees((hireacy[3].x + hireacy[0].x) / 2, (hireacy[3].y + hireacy[0].y) / 2));}}const promise = Cesium.sampleTerrainMostDetailed(_this.config.terrainProvider, slopelineposition);promise.then(function (updatedPositions) {//拿到所有的高度数据let heighmm = [];let m = 0//计算坡度比的次数let countcolor1 = 0;let countcolor2 = 0;let countcolor3 = 0;let countcolor4 = 0;let countcolor5 = 0;let countcolor6 = 0;let countcolor7 = 0;for (let k = 0; k < updatedPositions.length / 8; k++) {//第一个点与第五个点的坡度let slope1 = (updatedPositions[m].height - updatedPositions[m + 4].height) / (Cesium.Cartesian3.distance(Cesium.Cartesian3.fromDegrees(updatedPositions[m].latitude, updatedPositions[m].longitude, updatedPositions[m].height),Cesium.Cartesian3.fromDegrees(updatedPositions[m + 4].latitude, updatedPositions[m + 4].longitude, updatedPositions[m + 4].height)))//第二个点与第六个点的坡度let slope2 = (updatedPositions[m + 1].height - updatedPositions[m + 5].height) / (Cesium.Cartesian3.distance(Cesium.Cartesian3.fromDegrees(updatedPositions[m + 1].latitude, updatedPositions[m + 1].longitude, updatedPositions[m + 1].height),Cesium.Cartesian3.fromDegrees(updatedPositions[m + 5].latitude, updatedPositions[m + 5].longitude, updatedPositions[m + 5].height)))//第三个点与第七个点的坡度let slope3 = (updatedPositions[m + 2].height - updatedPositions[m + 6].height) / (Cesium.Cartesian3.distance(Cesium.Cartesian3.fromDegrees(updatedPositions[m + 2].latitude, updatedPositions[m + 2].longitude, updatedPositions[m + 2].height),Cesium.Cartesian3.fromDegrees(updatedPositions[m + 6].latitude, updatedPositions[m + 6].longitude, updatedPositions[m + 6].height)))//第四个点与第八个点的坡度let slope4 = (updatedPositions[m + 3].height - updatedPositions[m + 7].height) / (Cesium.Cartesian3.distance(Cesium.Cartesian3.fromDegrees(updatedPositions[m + 3].latitude, updatedPositions[m + 3].longitude, updatedPositions[m + 3].height),Cesium.Cartesian3.fromDegrees(updatedPositions[m + 7].latitude, updatedPositions[m + 7].longitude, updatedPositions[m + 7].height)))// console.log("slope1:"+slope1+";slope2:"+slope2+";slope3:"+slope3+";slope4:"+slope4);let arrposition = [Math.abs(slope1), Math.abs(slope2), Math.abs(slope3), Math.abs(slope4)];//取绝对值arrposition.sort();let slope = arrposition[3]; // 拿到最大的坡度值let lineposition = [];//画方向线的坐标if (slope == Math.abs(slope1)) {if (slope1 > 0) {lineposition.push(Cesium.Math.toDegrees(updatedPositions[m].longitude), Cesium.Math.toDegrees(updatedPositions[m].latitude),Cesium.Math.toDegrees(updatedPositions[m + 4].longitude), Cesium.Math.toDegrees(updatedPositions[m + 4].latitude));} else {lineposition.push(Cesium.Math.toDegrees(updatedPositions[m + 4].longitude), Cesium.Math.toDegrees(updatedPositions[m + 4].latitude),Cesium.Math.toDegrees(updatedPositions[m].longitude), Cesium.Math.toDegrees(updatedPositions[m].latitude));}} else if (slope == Math.abs(slope2)) {if (slope2 > 0) {lineposition.push(Cesium.Math.toDegrees(updatedPositions[m + 1].longitude), Cesium.Math.toDegrees(updatedPositions[m + 1].latitude),Cesium.Math.toDegrees(updatedPositions[m + 5].longitude), Cesium.Math.toDegrees(updatedPositions[m + 5].latitude));} else {lineposition.push(Cesium.Math.toDegrees(updatedPositions[m + 5].longitude), Cesium.Math.toDegrees(updatedPositions[m + 5].latitude),Cesium.Math.toDegrees(updatedPositions[m + 1].longitude), Cesium.Math.toDegrees(updatedPositions[m + 1].latitude));}} else if (slope == Math.abs(slope3)) {if (slope3 > 0) {lineposition.push(Cesium.Math.toDegrees(updatedPositions[m + 2].longitude), Cesium.Math.toDegrees(updatedPositions[m + 2].latitude),Cesium.Math.toDegrees(updatedPositions[m + 6].longitude), Cesium.Math.toDegrees(updatedPositions[m + 6].latitude));} else {lineposition.push(Cesium.Math.toDegrees(updatedPositions[m + 6].longitude), Cesium.Math.toDegrees(updatedPositions[m + 6].latitude),Cesium.Math.toDegrees(updatedPositions[m + 2].longitude), Cesium.Math.toDegrees(updatedPositions[m + 2].latitude));}} else if (slope == Math.abs(slope4)) {if (slope4 > 0) {lineposition.push(Cesium.Math.toDegrees(updatedPositions[m + 3].longitude), Cesium.Math.toDegrees(updatedPositions[m + 3].latitude),Cesium.Math.toDegrees(updatedPositions[m + 7].longitude), Cesium.Math.toDegrees(updatedPositions[m + 7].latitude));} else {lineposition.push(Cesium.Math.toDegrees(updatedPositions[m + 7].longitude), Cesium.Math.toDegrees(updatedPositions[m + 7].latitude),Cesium.Math.toDegrees(updatedPositions[m + 3].longitude), Cesium.Math.toDegrees(updatedPositions[m + 3].latitude));}}slope = (Math.abs(slope1) + Math.abs(slope2) + Math.abs(slope3) + Math.abs(slope4)) / 4; //四个坡度值大小有的差值特别大,这里取的平均值用来配置颜色//console.log(slope);let slopecolor;if (0 <= slope && slope < 0.29) {slopecolor = '#ff9090'countcolor1++;} else if (0.29 <= slope && slope < 0.5) {slopecolor = '#ff8080'countcolor2++;} else if (0.5 <= slope && slope < Math.sqrt(2) / 2) {slopecolor = '#ff7070'countcolor3++;} else if (Math.sqrt(2) / 2 <= slope && slope < 0.87) {slopecolor = '#ff6060'countcolor4++;} else if (0.87 <= slope && slope < 0.91) {slopecolor = '#ff5050'countcolor5++;} else if (0.91 <= slope && slope < 0.95) {slopecolor = '#ff4040'countcolor6++;} else {slopecolor = '#ff3030'countcolor7++;}_this.viewer.entities.add({//type: 'drawSloperectange',rectangle: {coordinates: Cesium.Rectangle.fromDegrees(Cesium.Math.toDegrees(updatedPositions[m].longitude), Cesium.Math.toDegrees(updatedPositions[m].latitude),Cesium.Math.toDegrees(updatedPositions[m + 4].longitude), Cesium.Math.toDegrees(updatedPositions[m + 4].latitude)),material: Cesium.Color.fromCssColorString(slopecolor)},});……}});}}}</script>
源码下载

夜雨聆风
