自学内容网 自学内容网

vue3 + ts + cesium:绘制、更新多边形 polygon

本文主要实现最基础的绘制多边形,并且可以拖动多边形的顶点实时更新多边形的形状。

实现效果:

    (1)单击鼠标左键绘制多边形、选中多边形;

    (2)单击鼠标右键结束绘制、结束更新多边形(此时不会显示多边形的顶点);

    (3)长按鼠标左键拖动多边形的顶点,实时更新多边形的形状;

    (4)抬起鼠标左键停止拖动多边形的顶点。

1. components / CesiumViewer / hooks / drawPolygon.ts

import * as Cesium from "cesium";
import {
    disableDefaultScreenSpaceEventHandlers,
    enableDefaultScreenSpaceEventHandlers
} from "@/components/CesiumViewer/hooks/utils";

export const drawPolygon = () => {
    const handler = new Cesium.ScreenSpaceEventHandler(window.viewer.scene.canvas)
    let isDrawing = true // 是否处于绘制状态
    let positions: any[] = [] // 当前绘制的多边形上的点的坐标
    let points: any[] = [] // 当前绘制的多边形的点的实体
    let polygonPositions: any[] = [] // 选中的多边形的位置
    let pickedPolygon: any = null // 选中的多边形
    let polygonPoints: any[] = [] // 选中的多边形的点实体
    // 单击左键 —— 绘制多边形
    handler.setInputAction((event: any) => {
        const pickedObject = window.viewer.scene.pick(event.position) // 拾取实体
        if (Cesium.defined(pickedObject) && pickedObject.id && pickedObject.id.polygon && !isDrawing) { // 选中多边形
            pickedPolygon = pickedObject.id.polygon
            polygonPositions = pickedObject.id.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions /* 获取多边形实体的位置 */
            polygonPositions.forEach((item: any) => {
                const polygonPoint = window.viewer.entities.add({
                    position: item,
                    point: {
                        pixelSize: 10,
                        color: Cesium.Color.fromCssColorString('#ffff00'),
                        scaleByDistance: new Cesium.NearFarScalar(1.5e2, 2.0, 8.0e6, 0.0),
                        heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
                    }
                })
                polygonPoints.push(polygonPoint) // 暂存选中的多边形的点实体
            })
        } else { // 绘制多边形
            const cartesian = window.viewer.camera.pickEllipsoid(event.position, window.viewer.scene.globe.ellipsoid)
            if (Cesium.defined(cartesian) && isDrawing) {
                const point = window.viewer.entities.add({ // 添加线上的点
                    position: cartesian,
                    point: {
                        pixelSize: 10, /* 点的大小 */
                        color: Cesium.Color.fromCssColorString('#ffff00'), /* 点的颜色 */
                        /* 根据视角远近控制点的比例 */
                        scaleByDistance: new Cesium.NearFarScalar(1.5e2, 2.0, 8.0e6, 0.0),
                        heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND
                    }
                })
                positions.push(cartesian) // 暂存点坐标
                points.push(point) // 暂存点实体
                if (positions.length > 2) { // 最少三点成面
                    window.viewer.entities.add({
                        polygon: {
                            hierarchy: new Cesium.CallbackProperty(() => {
                                return new Cesium.PolygonHierarchy(positions)
                            }, false),
                            material: Cesium.Color.fromCssColorString('#ff0000').withAlpha(0.5), /* 颜色 && 透明度 */
                        }
                    })
                }
            }
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
    // 单击右键 —— 结束绘制 / 结束更新多边形
    handler.setInputAction(() => {
        isDrawing = false // 结束绘制
        points.forEach((item: any) => {
            window.viewer.entities.remove(item) // 移除刚刚绘制的多边形上的点
        })
        if (polygonPoints.length > 1) {
            polygonPoints.forEach((item: any) => {
                window.viewer.entities.remove(item) // 移除选中的多边形的顶点
            })
            polygonPoints = []
        }
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
    // 长按左键 —— 拖动多边形上的点
    handler.setInputAction((event: any) => {
        const pickedObject = window.viewer.scene.pick(event.position)
        if (Cesium.defined(pickedObject) && pickedObject.id && pickedObject.id.point) {
            const pickedPointPosition = pickedObject.id.position.getValue(Cesium.JulianDate.now()) // 被选择拖动的点的初始位置
            // 当前更新的多边形上的点的位置的索引
            const index = polygonPositions.findIndex((item: any) => item.x === pickedPointPosition.x && item.y === pickedPointPosition.y && item.z === pickedPointPosition.z)
            disableDefaultScreenSpaceEventHandlers() // 拖动点时禁止屏幕移动
            handler.setInputAction((movement: any) => {
                const newPosition = window.viewer.camera.pickEllipsoid(movement.endPosition, window.viewer.scene.globe.ellipsoid)
                if (Cesium.defined(newPosition)) {
                    pickedObject.id.position = new Cesium.CallbackProperty(() => { // 动态更新点的位置
                        return newPosition
                    }, false)
                    polygonPositions[index] = newPosition
                    pickedPolygon.hierarchy = new Cesium.CallbackProperty(() => { // 动态更新多边形
                        return new Cesium.PolygonHierarchy(polygonPositions)
                    }, false)
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
        }
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN)
    // 抬起左键 —— 停止拖动
    handler.setInputAction(() => {
        handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE) // 清除鼠标移动事件,停止拖动点
        enableDefaultScreenSpaceEventHandlers() // 拖动完成,允许屏幕移动
    }, Cesium.ScreenSpaceEventType.LEFT_UP)
}

2. components / CesiumViewer / hooks / utils.ts

// 保持地球不动
export function disableDefaultScreenSpaceEventHandlers() {
    window.viewer.scene.screenSpaceCameraController.enableRotate = false // 禁止旋转
    window.viewer.scene.screenSpaceCameraController.enableTranslate = false // 禁止平移
    window.viewer.scene.screenSpaceCameraController.enableZoom = false // 禁止缩放
    window.viewer.scene.screenSpaceCameraController.enableTilt = false // 禁止倾斜
    window.viewer.scene.screenSpaceCameraController.enableLook = false // 禁止观察(自由视角查看)
}

// 允许地球移动
export function enableDefaultScreenSpaceEventHandlers() {
    window.viewer.scene.screenSpaceCameraController.enableRotate = true
    window.viewer.scene.screenSpaceCameraController.enableTranslate = true
    window.viewer.scene.screenSpaceCameraController.enableZoom = true
    window.viewer.scene.screenSpaceCameraController.enableTilt = true
    window.viewer.scene.screenSpaceCameraController.enableLook = true
}


原文地址:https://blog.csdn.net/Serenity_Qin/article/details/142525545

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!