cesium绘制实时绘制多边形并编辑多边形

前言:基于cesium实现画多边形以及对其编辑

效果:cesium绘制实时绘制多边形并编辑多边形_哔哩哔哩_bilibili

思路:

        1.创建cesium (省略.....)

        2.理清需要那些功能,在这里我们用到了cesium得画点,画线,画面,以及对鼠标得左键,右键,和移动得监听

        3.接下来就开始创作了,其中还有一些细节,大家自行体会,

话不多说直接上代码

完整代码如下,当然还有一些缺陷或者bug,请大家指正,我会改进

// 画面点位数据
let pointArr = []
// 当前点位的数据
let nowPoint = []
// 当前多边形中的点和线实体集合
let pointAndLineEntity = {
    pointEntityArr: [],
    lineEntityArr: [],
    demoLineEntityArr: [],
    polygonEntityArr: []
}
// 当前选择的编辑点
let nowEditPoint = []
// 是否开始画多边形
let isDrawLine = false
// 是否形成面
let isDrawPolyGon = false
// 事件
const editPolyGonFunC = {
    // 删除实体
    // 删除鼠标移动生成的线
    delDemoEntity: (name) => {
        name == 'point_name' && pointAndLineEntity.pointEntityArr.forEach(item => {
            viewer.entities.remove(item)
        })
        name == 'line_name' && pointAndLineEntity.lineEntityArr.forEach(item => {
            viewer.entities.remove(item)
        })
        name == 'line_demo_name' && pointAndLineEntity.demoLineEntityArr.forEach(item => {
            viewer.entities.remove(item)
        })
    },
    // 画面
    draw: () => {
        // 经纬度转换
        const getLonOrLat = (cartesian2) => {
            var cartesian = viewer.scene.globe.pick(viewer.camera.getPickRay(cartesian2), viewer.scene);
            // console.log('cartesian',cartesian);
            let cartorgraphic = Cesium.Cartographic.fromCartesian(cartesian);
            // console.log('ddd', cartorgraphic);
            let lon = Cesium.Math.toDegrees(cartorgraphic.longitude);  // 经度
            let lat = Cesium.Math.toDegrees(cartorgraphic.latitude);   // 纬度  
            // console.log(`经度:${lon},纬度:${lat}`);
            return {
                longitude: lon,
                latitude: lat
            }
        }
        // 画点
        const drawPoint = (lonAndLat) => {
            const entityPoint = viewer.entities.add({
                position: Cesium.Cartesian3.fromDegrees(lonAndLat[0], lonAndLat[1], lonAndLat[2]),
                name: 'point_name',
                point: {
                    color: Cesium.Color.fromCssColorString('#fc3d4a'),
                    outlineColor: Cesium.Color.fromCssColorString('#fc3d4a'),
                    pixelSize: 11
                },
            })
            return entityPoint
        }
        // 画线
        const drawLine = (name, lineArr) => {
            const entityLine = viewer.entities.add({
                name: name,
                polyline: {
                    positions: Cesium.Cartesian3.fromDegreesArrayHeights(lineArr),
                    width: 5,
                    material: Cesium.Color.fromCssColorString('#fcc31f'),
                }
            })
            return entityLine
        }
        // 画面
        const drawPolyGon = (lonAndLat) => {
            let lonLats = (data) => {
                let arr = []
                for (let d in data) {
                    //判断经纬度范围
                    if (
                        data[d][0] >= -180 &&
                        data[d][0] <= 180 &&
                        data[d][1] >= -90 &&
                        data[d][1] <= 90
                    ) {
                        arr.push(data[d][0], data[d][1])
                    } else {
                        console.log('经纬度数值不对:', data[d][0], data[d][1])
                    }
                }
                return arr
            }
            viewer.entities.add({
                // position: Cesium.Cartesian3.fromDegrees(lonAndLat[0], lonAndLat[1], lonAndLat[2]),
                name: "polyGon_name",
                polygon: {
                    clampToGround: true, //开启贴地
                    hierarchy: new Cesium.PolygonHierarchy(
                        Cesium.Cartesian3.fromDegreesArray(lonLats(lonAndLat))
                    ),
                    material: Cesium.Color.BLUE.withAlpha(0.5),
                    // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 300000)
                }
            });
        }

        // 声明监听事件
        let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas)
        // 监听鼠标左击事件
        handler.setInputAction((event) => {
            // console.log('ddd', event);
            let pick = viewer.scene.pick(event.position)
            // console.log('ddd pick', pick);
            // 判断是否有实体
            if (pick && pick.id && pick.id.polygon) {
                if (!pointAndLineEntity.polygonEntityArr.includes(pick) && pointAndLineEntity.polygonEntityArr.length == 0) {
                    // 实体存在生成编辑点
                    for (let cartesian of pick.id.polygon.hierarchy._value.positions) {
                        const point = viewer.entities.add({
                            name: "polygon_point",
                            position: cartesian,
                            point: {
                                color: Cesium.Color.WHITE,
                                pixelSize: 8,
                                outlineColor: Cesium.Color.BLACK,
                                outlineWidth: 1,
                            },
                        });

                        // 保存点的ID以便删除
                        pointAndLineEntity.pointEntityArr.push(point)
                    }
                    pointAndLineEntity.polygonEntityArr.push(pick)

                } else {
                    console.log('已生成编辑点,或只能存在一个');
                }

            } else if (pick && pick.id && pick.id.point && (pick.id.name == 'polygon_point')) {
                console.log('编辑点保存');
                nowEditPoint = []
                nowEditPoint.push(pick)
                isDrawPolyGon = true
                // console.log('ddd pointAndLineEntity', pointAndLineEntity);
                // console.log('ddd nowEditPoint', nowEditPoint);
            } else {
                // 实体不存在开始画多边形
                if (!isDrawPolyGon) {
                    // 获取坐标信息
                    let nowPosition = getLonOrLat(event.position)

                    // 点数据保存
                    pointArr.push([nowPosition.longitude, nowPosition.latitude, 0])
                    // console.log('pointArr', pointArr);
                    // 当前点数据
                    nowPoint = [nowPosition.longitude, nowPosition.latitude, 0]

                    // 画点
                    const point = drawPoint([nowPosition.longitude, nowPosition.latitude, 0])
                    pointAndLineEntity.pointEntityArr.push(point)

                    // 开始画多边形
                    isDrawLine = true
                    // 画线
                    const num = pointArr.length
                    if (num > 1) {
                        editPolyGonFunC.delDemoEntity('line_demo_name')
                        const line = drawLine('line_name', [...pointArr[num - 2], ...pointArr[num - 1]])
                        pointAndLineEntity.lineEntityArr.push(line)
                    }
                } else {

                }
            }



        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
        // 鼠标移动事件
        handler.setInputAction((event) => {
            if (isDrawLine && !isDrawPolyGon) {
                // 画框逻辑
                // -------
                // console.log('ddd event', event);
                // 获取坐标信息
                let movePosition = getLonOrLat(event.startPosition)
                // console.log('ddd nowPosition', movePosition);
                // 删除上一次生成
                editPolyGonFunC.delDemoEntity('line_demo_name')
                // 创建线
                const demoLine = drawLine('line_demo_name', [...nowPoint, ...[movePosition.longitude, movePosition.latitude, 0]])
                pointAndLineEntity.demoLineEntityArr.push(demoLine)
            } else if (isDrawPolyGon && !isDrawLine) {
                // 编辑逻辑
                // -------
                // 获取坐标信息
                let movePosition = getLonOrLat(event.startPosition)
                // 更新点坐标
                nowEditPoint[0].id.position = Cesium.Cartesian3.fromDegrees(movePosition.longitude, movePosition.latitude, 0)
                // 获取更新面坐标的数据
                let points = [];
                pointAndLineEntity.pointEntityArr.forEach(item => {
                    points.push(item.position._value);
                })
                // console.log('points',points);
                // 更新面坐标
                pointAndLineEntity.polygonEntityArr[0].id.polygon.hierarchy = points;

            }

        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
        // 鼠标右击事件
        handler.setInputAction((event) => {
            // console.log('ddd event', event);
            if (!isDrawPolyGon && isDrawLine) {
                // 结束画多边形
                isDrawLine = false
                // 删除鼠标移动画线
                editPolyGonFunC.delDemoEntity('line_demo_name')
                // 封闭多边形
                // const num = pointArr.length
                // drawLine('line_name', [...pointArr[num - 1], ...pointArr[0]])
                // 画多边形结束,形成面开始
                drawPolyGon(pointArr)

                // 清空数据
                // 删除画点以及画线
                editPolyGonFunC.delDemoEntity('line_name')
                editPolyGonFunC.delDemoEntity('point_name')
                pointArr = []
                nowPoint = []
                pointAndLineEntity = {
                    pointEntityArr: [],
                    lineEntityArr: [],
                    demoLineEntityArr: [],
                    polygonEntityArr: []
                }

                // console.log('ddd', viewer.entities);
                // console.log('ddd', viewer);
                // isDrawPolyGon = true
            } else if (isDrawPolyGon && !isDrawLine) {
                isDrawPolyGon = false
            }


        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)

    },

    // 重置
    klk: () => {
        editPolyGonFunC.delDemoEntity('point_name')
        isDrawLine = false
        isDrawPolyGon = false
        pointAndLineEntity = {
            pointEntityArr: [],
            lineEntityArr: [],
            demoLineEntityArr: [],
            polygonEntityArr: []
        }
        nowEditPoint = []
    }
}

最后谢谢大家观看,第一次创作,感谢大家!

如有不好的地方,欢迎指正.

也作为在工作当中的积累,展示在这里.

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值