Cesium保姆教程之绘制任意多边形
本人是一个cesium小白,对于cesium理解的不是非常透彻,因此只能根据自己的理解和网上的大佬教程进行编写,把工作中所涉及到的cesium工作,做成一个一个小功能效果,由于本人刚开始写文章,导致文章多处语句不通顺流畅,请见谅,由于工作和自己的原因,导致了自己很久没有写文章,也没有对cesium进行提炼总结,打算这段时间对cesium进行总结提炼。本文所涉及到的前端技术栈主要是vue3+cesium,后续慢慢更新关于cesium效果的其他案例。
本篇是实现cesium的绘制任意多边形功能,参考案例:Drawing on Terrain - Cesium Sandcastle
思路:
鼠标左击事件:获取点,添加获取到的点(第一次左击的时候要添加两次点,这样会确保在鼠标移动的时候已经添加上多边形);
鼠标移动事件:移动,不断删除上一个点,并获取最后一个点的位置信息添加到多边形顶点中;
鼠标右击事件:结束绘制。
实现效果
实现代码
鼠标左击事件
js
handler.setInputAction((event) => {
let ray = viewer.camera.getPickRay(event.position);
let earthPosition = viewer.scene.globe.pick(ray, viewer.scene)
//鼠标开始点击多边形的第一个点
if (activeShapePoints.length === 0) {
//将第一个左击的点添加到多边形顶点集合中
activeShapePoints.push(earthPosition)
//多边形的坐标采用回调的形式
//边线顶点
let linePoints = new Cesium.CallbackProperty(() => {
let vertexPoints = activeShapePoints.concat([activeShapePoints[0]]);
return vertexPoints;
}, false)
//多边形顶点
let dynamicPositions = new Cesium.CallbackProperty(() => {
return new Cesium.PolygonHierarchy(activeShapePoints)
}, false)
//添加一个多边形
polygon = viewer.entities.add({
name: "Polygon",
id: id,
polyline: {
positions: linePoints,
width: outlineWidth,
material: outlineColor,
clampToGround: true
},
polygon: {
hierarchy: dynamicPositions,
material: color,
outlineColor: outlineColor,
height: 0
}
})
polygon.GeoType = "Polygon"
}
//将鼠标点击的点添加到多边形顶点集合中
activeShapePoints.push(earthPosition)
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
鼠标移动事件
js
//鼠标移动事件
handler.setInputAction((movement) => {
//获取鼠标所在的位置
const ray = viewer.camera.getPickRay(movement.endPosition)
const newPosition = viewer.scene.globe.pick(ray, viewer.scene)
//已经定义了polygon
if (Cesium.defined(polygon)) {
//删除多边形顶点中最新的一个点
activeShapePoints.pop()
//将最新获取到的点添加到多边形顶点集合中
activeShapePoints.push(newPosition)
}
if (activeShapePoints.length === 3) {
polygon.polygon.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
鼠标右击事件
js
handler.setInputAction((event) => {
//删除最后一个点(重复添加的点)
activeShapePoints.pop()
polygon.pottingPoint = activeShapePoints
//将所有的点添加到结果数组中
resList.push(polygon)
//销毁右击事件
handler.destroy()
if (typeof callback === "function") callback(polygon)
}, Cesium.ScreenSpaceEventType.RIGHT_DOWN)
完整源码
创建任意多边形createPolygon.js
js
const createPolygon = (viewer, resList, options, callback) => {
if (!viewer) throw new Error("no viewer object!")
options = options || {};
let id = options.id || getRandomId();
if (viewer.entities.getById(id)) {
throw new Error("the id is an unique value")
}
let color = options.color || Cesium.Color.WHITE;
let outlineColor = options.outlineColor || color.withAlpha(1)
// let outlineColor = color.withAlpha(1);
const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
// let tip = "左键点击开始绘制";
let activeShapePoints = [];
let polygon = undefined;
let floatingPoint = undefined;
let drawStatus = true;
//鼠标左击事件
handler.setInputAction((event) => {
let ray = viewer.camera.getPickRay(event.position);
let earthPosition = viewer.scene.globe.pick(ray, viewer.scene)
// debugger
//鼠标开始点击多边形的第一个点
if (activeShapePoints.length === 0) {
// debugger
floatingPoint = createPoint(viewer, earthPosition)
//将第一个左击的点添加到多边形顶点集合中
activeShapePoints.push(earthPosition)
//多边形的坐标采用回调的形式
//多边形边界顶点
let polylinePoints = new Cesium.CallbackProperty(() => {
let vertexPoints = activeShapePoints.concat([activeShapePoints[0]])
return vertexPoints
}, false)
//多边形顶点
let dynamicPositions = new Cesium.CallbackProperty(() => {
return new Cesium.PolygonHierarchy(activeShapePoints)
}, false)
//添加一个多边形
polygon = viewer.entities.add({
name: "Polygon",
id: id,
polyline: {
positions: polylinePoints,
width: 5,
material: outlineColor,
clampToGround: true
},
polygon: {
hierarchy: dynamicPositions,
material: color,
heightReference: Cesium.HeightReference.NONE
// outlineColor: outlineColor,
// height: 0
}
})
polygon.GeoType = "Polygon"
}
//将鼠标点击的点添加到多边形顶点集合中
activeShapePoints.push(earthPosition)
createPoint(viewer, earthPosition)
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//鼠标移动事件
handler.setInputAction((movement) => {
//获取鼠标所在的位置
const ray = viewer.camera.getPickRay(movement.endPosition);
const newPosition = viewer.scene.globe.pick(ray, viewer.scene);
//已经定义了polygon
if (Cesium.defined(polygon)) {
floatingPoint.position.setValue(newPosition);
console.log("object");
//删除多边形顶点中最新的一个点
activeShapePoints.pop()
//将最新获取到的点添加到多边形顶点集合中
activeShapePoints.push(newPosition)
}
if (activeShapePoints.length === 3) {
polygon.polygon.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
}
console.log("ssssssss");
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction((event) => {
//删除最后一个点(重复添加的点)
activeShapePoints.pop()
polygon.pottingPoint = activeShapePoints
//将所有的点添加到结果数组中
resList.push(polygon)
//销毁右击事件
handler.destroy()
drawStatus = false
if (typeof callback === "function") callback(polygon)
}, Cesium.ScreenSpaceEventType.RIGHT_DOWN)
}
前端调用
index.vue
vue
<template>
<div>
<div id="cesiumContainer">
<div class="plotting-tool">
<el-button @click="startDraw()">开始创建</el-button>
</div>
</div>
</div>
</template>
<script setup>
import * as Cesium from "cesium"
import "cesium/Source/Widgets/widgets.css"
import initCesium from "@/cesiumUtils/initCesium"
import createPolygon from "@/components/createPolygon";
import { onMounted } from "vue";
let viewer = null;
//生命周期钩子
onMounted(async () => {
viewer = await initCesium("cesiumContainer");
viewer.camera.lookAt(
Cesium.Cartesian3.fromDegrees(-122.2058, 46.1955, 1000.0),
new Cesium.Cartesian3(5000.0, 5000.0, 5000.0)
);
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
})
const startDraw = () => {
createPolygon(viewer, [],
{
color: Cesium.Color.BLUE,
outlineColor: Cesium.Color.GREEN
},
(e) => { console.log(e); }
)
}
</script>
<style lang="less" scoped>
#cesiumContainer {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
overflow: hidden;
position: relative;
}
.dynamic-trail-tools {
position: absolute;
border: 1px solid rgb(31, 30, 30);
border-radius: 5px;
background-color: rgba(66, 65, 66, 0.8);
z-index: 9999;
margin: 10px;
padding: 10px;
}
.edit {
position: absolute;
top: 0;
left: 0;
padding: 10px;
}
.plotting-tool {
position: absolute;
margin: 10px;
padding: 10px;
border: 1px solid rgb(39, 38, 38);
border-radius: 5px;
background-color: rgba(66, 65, 66, 0.8);
z-index: 10;
}
</style>
好了,以上就是本篇文章的全部内容,由于本人是第一次写这种技术博客,缺乏经验,语言也过于简单,请见谅。本篇后续也会不断修改完善,主要是对于点的获取不能仅仅局限于地形,也会在模型上进行绘制,这个会马上进行更新。文章中也有些许地方写的不对,请各位同学和同行进行批评指正,希望有你们的批评指正能让我的文章会越来越完善,自己对于cesium的理解也会越来越深,也希望大家对自己的研究的技术越来深入和精通。