Cesium保姆教程之绘制任意多边形

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的理解也会越来越深,也希望大家对自己的研究的技术越来深入和精通。

相关推荐
duansamve1 天前
WebGIS地图框架有哪些?
javascript·gis·openlayers·cesium·mapbox·leaflet·webgis
汪洪墩2 天前
【Mars3d】实现这个地图能靠左,不居中的样式效果
前端·javascript·vue.js·3d·webgl·cesium
vener_5 天前
Cesium用zoomTo函数实现对目标(各种实体)的视角控制
前端·javascript·cesium
智方科技9 天前
3DTiles之使用customShader调整风格
3d·智慧城市·cesium
山海鲸可视化9 天前
GIS融合之路(八)-如何用Cesium直接加载OSGB文件(不用转换成3dtiles)
3d·gis·数字孪生·cesium·倾斜摄影·osgb
智方科技9 天前
如何编译 Cesium 源码
3d·智慧城市·cesium·tilesbuilder
柳晓黑胡椒10 天前
cesiusm实现 多图例展示+点聚合(base64图标)
css3·canvas·base64·cesium·animation
智方科技小智10 天前
3DTiles之使用customShader调整风格
cesium
智方科技小智10 天前
3D Tiles 之 Geometry Error 介绍
cesium
一介青烟小生11 天前
cesium渲染3DTiles模型和glb模型
3d·cesium