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

相关推荐
不浪brown1 天前
爽翻了!Cesium手撸一个动态视锥体工具用于开发调试,效率翻倍(附完整源码)
cesium
木子李i2 天前
Cesium离线使用和部署地图影像
前端·cesium
全宝4 天前
🌏【cesium系列】01.vue3+vite集成Cesium
前端·gis·cesium
不浪brown11 天前
地下管网的产品经理问我:能不能用Cesium在地表挖一个洞,让我直观的看到地下的管道(附开源代码)
cesium
熟悉不过17 天前
cesium项目之cesiumlab地形数据加载
前端·javascript·vue.js·cesium·webgis·cesiumlab
前端小菜鸟一枚s18 天前
`ConstantPositionProperty` 的使用与应用
前端·javascript·cesium
前端小菜鸟一枚s18 天前
`ConstantProperty` 的使用与应用
前端·javascript·cesium
不浪brown18 天前
【实战篇】Cesium Shader实现军事级雷达探测波!数字孪生开发者必学(附开源代码)
cesium
阿铎前端19 天前
Cesium系列:从入门到实践,打造属于你的3D地球应用
vue·cesium
放逐者-保持本心,方可放逐23 天前
Cesium 核心思想及基础概念应用
scene·cesium·camera·entity·primitive·viewer