相关概念
-
Viewer:new Cesium.Viewer (container, options )
-
介绍:用于构建应用程序的基本小部件。它将所有标准Cesium小部件组合到一个可重用的程序包中。
-
Entity:new Cesium.Entity ( options )
-
介绍:实体实例将多种形式的可视化聚集到单个高级对象中。可以手动创建它们并将其添加到 Viewer#entities
-
介绍:描述 Rectangle 的图形。矩形符合地球的曲率,可以放置在表面或可以选择将其挤出成一定体积。
-
coordinates:Cesium.Rectangle.fromDegrees ( west , south , east , north , result )
-
介绍:定义了矩形的坐标
-
material:略
-
介绍:定义了矩形的材质
demo效果
完整代码展示
其中用到了EventBus来进行组件通讯,来触发相应的逻辑,大家可以用点击事件等来代替。
<template>
<div id="CesiumMapOne"></div>
<div class="cesium-lnglat-info" v-show="showLngLat">
{{ lngNum }},{{ latNum }}
</div>
</template>
<script setup>
// vue
import {
ref,
reactive,
watch,
watchEffect,
computed,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
defineProps,
defineEmits,
} from "vue";
// cesium
import * as Cesium from "cesium";
import "cesium/Build/CesiumUnminified/Widgets/widgets.css";
window.CESIUM_BASE_URL = "../../../node_modules/cesium/Build/CesiumUnminified/";
// eventbus
import EventBus from "@/eventbus";
// 变量
let _viewer = null;
// 经纬度
let lngNum = ref(0);
let latNum = ref(0);
// 是否显示经纬度
let showLngLat = ref(false);
// 裁剪AOI
let drawFlag = false;
// 开始点击位置
let startPoint = null;
// 结束点击位置
let endPoint = null;
// 绘制动态矩形数组
let pointsArr = [];
// 裁剪矩形 实体
let JXBox = null;
// 初始化地图
function initMap() {
Cesium.Ion.defaultAccessToken =
"在这里输入你在Cesium申请的开发token";
//开发token
const viewer = new Cesium.Viewer("CesiumMapOne", {
//第二个参数是个对象
// terrainProvider: Cesium.createWorldTerrainAsync(),
// 地形服务
timeline: false,
// 时间轴控件
animation: false,
// 动画控件
geocoder: false,
//搜索框控件
navigationHelpButton: false,
// 帮助按钮
sceneModePicker: true,
// 场景模式选择器
fullscreenButton: false,
// 全屏按钮
baseLayerPicker: false,
// 底图选择器
infoBox: false,
// 信息框
selectionIndicator: false,
// 选中指示器
homeButton: false,
// 首页按钮
// scene3DOnly: true,
// 3D模式
// creditContainer: "cesiumjsdiv",
// 显示版权信息
// creditViewport:"cesiumjsdiv",
// 显示版权信息
});
//关键的一步,之后所有的API从这里开始
_viewer = viewer;
// Cesium鼠标移动事件
_viewer.screenSpaceEventHandler.setInputAction(function (movement) {
//获取当前鼠标位置
var cartesian = _viewer.camera.pickEllipsoid(
movement.endPosition,
_viewer.scene.globe.ellipsoid
);
//判断鼠标位置是否在模型上
if (cartesian) {
//获取当前鼠标位置的经纬度
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
// console.log(cartographic, "当前鼠标位置");
let longitude = Cesium.Math.toDegrees(cartographic.longitude);
let latitude = Cesium.Math.toDegrees(cartographic.latitude);
showLngLat.value = true;
if (longitude < 0) {
lngNum.value = Math.abs(longitude).toFixed(6) + "°W";
} else {
lngNum.value = longitude.toFixed(6) + "°E";
}
if (latitude < 0) {
latNum.value = Math.abs(latitude).toFixed(6) + "°S";
} else {
latNum.value = latitude.toFixed(6) + "°N";
}
if (drawFlag) {
endPoint = {
lng: longitude,
lat: latitude,
};
//这段代码允许 以任意方向来动态绘制矩形
if (endPoint.lng < startPoint.lng && endPoint.lat > startPoint.lat) {
// 第二象限
pointsArr = Cesium.Rectangle.fromDegrees(
endPoint.lng,
startPoint.lat,
startPoint.lng,
endPoint.lat
);
} else if (
endPoint.lng > startPoint.lng &&
endPoint.lat > startPoint.lat
) {
// 第一象限
pointsArr = Cesium.Rectangle.fromDegrees(
startPoint.lng,
startPoint.lat,
endPoint.lng,
endPoint.lat
);
} else if (
endPoint.lng < startPoint.lng &&
endPoint.lat < startPoint.lat
) {
// 第三象限
pointsArr = Cesium.Rectangle.fromDegrees(
endPoint.lng,
endPoint.lat,
startPoint.lng,
startPoint.lat
);
} else {
// 第四象限
pointsArr = Cesium.Rectangle.fromDegrees(
startPoint.lng,
endPoint.lat,
endPoint.lng,
startPoint.lat
);
}
}
} else {
showLngLat.value = false;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}
// 开始绘制矩形 函数
function clipAoi() {
//鼠标左点击 事件
_viewer.screenSpaceEventHandler.setInputAction(function (e) {
// 获取鼠标点击位置
let cartesian = _viewer.camera.pickEllipsoid(
e.position,
_viewer.scene.globe.ellipsoid
);
// 判断 是否作用在地球上
if (cartesian && !drawFlag) {
// 获取经纬度
let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
let longitude = Cesium.Math.toDegrees(cartographic.longitude);
let latitude = Cesium.Math.toDegrees(cartographic.latitude);
// 获取当前相机高度
// let height = _viewer.camera.positionCartographic.height;
startPoint = {
lng: longitude,
lat: latitude,
};
drawFlag = true;
// 初始化矩形
pointsArr = Cesium.Rectangle.fromDegrees(0, 0, 0, 0);
//删除矩形实体
if (JXBox) {
_viewer.entities.remove(JXBox);
}
// 添加动态矩形实体
JXBox = _viewer.entities.add({
rectangle: {
coordinates: new Cesium.CallbackProperty(() => {
return pointsArr;
}, false),
material: Cesium.Color.fromCssColorString("rgba(0, 255, 255, .5)"),
outline: true, //多边形是否显示边缘线
outlineColor: Cesium.Color.YELLOW.withAlpha(0.8), //定义多边形边缘线的颜色。
outlineWidth: 2, //控制多边形边缘线的宽度。
height: 5, //指定多边形相对于椭球表面的高度。
extrudedHeight: 10, //创建一个拉伸的多边形(即具有高度的立体),可以设置此参数为多边形顶部的高度。
},
});
} else if (cartesian && drawFlag) {
drawFlag = false;
EventBus.emit("drawOK", pointsArr);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
// 重置矩形函数
function resetAoi() {
if (JXBox) {
_viewer.entities.remove(JXBox);
}
// 移除 Cesium 的鼠标左点击事件
_viewer.screenSpaceEventHandler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_CLICK
);
//
EventBus.emit("resetAoi");
}
// 页面挂载后
onMounted(() => {
initMap();
EventBus.on("header", (data) => {
console.log(data, "header-msg");
// 触发 对应逻辑
switch (data) {
case "裁剪AOI":
clipAoi();
break;
case "重置AOI":
resetAoi();
break;
default:
break;
}
});
});
// 页面销毁前
onBeforeUnmount(() => {
// 销毁
EventBus.off("header");
if (_viewer) {
_viewer.destroy();
}
});
</script>
<style lang="scss" scoped>
#CesiumMapOne {
width: 100%;
height: 100%;
overflow: hidden;
}
.cesium-lnglat-info {
width: 290px;
height: 46px;
font-weight: 600;
font-size: 18px;
color: #3bde80;
display: flex;
justify-content: center;
align-items: center;
border-radius: 23px;
border: 1px solid #fff;
background-color: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(10px);
/* 背景模糊效果 */
position: absolute;
bottom: 30px;
right: 30px;
z-index: 10;
}
</style>
部分代码描述
-
coordinates是矩形的坐标,它使用callbackProperty来动态更新
-
callbackProperty是一个特殊的属性类型,用于允许属性值动态更新。回调函数返回的是
pointsArr
,它表示矩形的坐标数组。 -
第二个参数
false
表示该回调函数的更新频率是静态的(即不需要每帧都更新),只有当this.posArr
发生变化时才会重新计算。