cesium地图拉取矩形框

前言:基于cesium实现地图拉取矩形框

效果:https://www.bilibili.com/video/BV1NQ4y1A7B6/?spm_id_from=333.999.0.0

思路:

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

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

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

话不多说直接上代码

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


// 当前点位的数据
let nowPoint = []
// 当前多边形中的点和线实体集合
let polygonEntityArr = []
let pointEntityArr = []
// 是否开始画多边形
let isDrawLine = false
// 是否形成面
let isDrawPolyGon = false
// 事件
const drawRectangleFunC = {
    // 删除实体
    // 删除鼠标移动生成的线
    delDemoEntity: (name) => {
        name == 'point_name' && pointEntityArr.forEach(item => {
            viewer.entities.remove(item)
        })
    },
    // 画面
    draw: () => {
        // 经纬度转换
        const getLonOrLat = (cartesian2) => {
            let 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 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
            }
            const entityPolygon = 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)
                }
            });
            return entityPolygon
        }

        // 声明监听事件
        let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas)
        // 监听鼠标左击事件
        handler.setInputAction((event) => {
            if (isDrawLine) {
                // console.log('ddd', event);
                // 判断是否有实体
                // 获取坐标信息
                let nowPosition = getLonOrLat(event.position)

                // 当前点数据
                nowPoint = [nowPosition.longitude, nowPosition.latitude, 0]

                // 画点
                const point = drawPoint([nowPosition.longitude, nowPosition.latitude, 0])
                pointEntityArr.push(point)
                // 开始形成面
                isDrawPolyGon = true
            }




        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
        // 鼠标移动事件
        handler.setInputAction((event) => {
            // 画框逻辑
            if (isDrawLine && (nowPoint.length > 0)) {
                setTimeout(() => {


                    // -------
                    // console.log('ddd event', event);
                    // 获取坐标信息
                    let movePosition = getLonOrLat(event.startPosition)
                    // console.log('ddd nowPosition', movePosition);


                    const getRectanglePoint = (startPoint, endPoint) => {
                        //点转turf点
                        let p1 = turf.point([...startPoint]);
                        let p2 = turf.point([...endPoint]);
                        // 两点间距离
                        let p1p2 = turf.rhumbDistance(p1, p2, { units: 'miles' });
                        let p1p2bearing = turf.bearing(p1, p2);
                        // console.log('ddd bearing', bearing);

                        // p1 ---------- p3
                        //    | \      |
                        //    |   \    |
                        //    |     \  |
                        //    |       \|
                        // p4 ---------- p2
                        // 获取生成的两个延长线点

                        // 获取延长线点
                        const getExtensionPoint = (point, distance, bearing) => {
                            // let startPoint = turf.point(point, { "marker-color": "F00" });
                            const demo = turf.rhumbDestination(point, distance, bearing, { units: 'miles' });
                            return demo.geometry.coordinates
                        }

                        // 获取生成的两个延长线点
                        let p3RBearing = 0
                        let p3TBearing = 0
                        let p4RBearing = 0
                        let p4TBearing = 0
                        // turf使用的角度是由北向南

                        //    北
                        //     |
                        //     |
                        //     |
                        //     | 
                        //   p |----------------- 
                        //     |
                        //     |
                        //     |
                        //     |
                        //     |
                        //    南

                        if (p1p2bearing > 0) {
                            if (p1p2bearing < 90) {
                                // 在0 - 90度范围内
                                p3RBearing = 0
                                p3TBearing = -90
                                p4RBearing = 90
                                p4TBearing = -180
                            } else {
                                // 在90 - 180度范围内
                                p3RBearing = 90
                                p3TBearing = 0
                                p4RBearing = -180
                                p4TBearing = -90
                            }
                        } else {
                            if (p1p2bearing > -90) {
                                // 在0 - -90度范围内
                                p3RBearing = -90
                                p3TBearing = -180
                                p4RBearing = 0
                                p4TBearing = 90
                            } else {
                                // 在-90 - -180度范围内
                                p3RBearing = -180
                                p3TBearing = 90
                                p4RBearing = -90
                                p4TBearing = 0
                            }
                        }
                        // 获取p3点
                        const p3R = getExtensionPoint(p1, p1p2, p3RBearing)  //起点
                        const p3T = getExtensionPoint(p2, p1p2, p3TBearing)  //终点(鼠标当前对应的点)
                        // 获取p4点
                        const p4R = getExtensionPoint(p1, p1p2, p4RBearing)  //起点
                        const p4T = getExtensionPoint(p2, p1p2, p4TBearing)  //终点(鼠标当前对应的点)
                        //根据两个延长线获取交点 即p3
                        const getLineIntersect = (pp1, pp2) => {
                            let line1 = turf.lineString([[...startPoint], [...pp1]]);
                            let line2 = turf.lineString([[...endPoint], [...pp2]]);
                            let intersects = turf.lineIntersect(line1, line2);
                            const ddd = intersects.features.length > 0 ? intersects.features[0].geometry.coordinates : ''
                            return ddd
                        }

                        const p3 = getLineIntersect(p3R, p3T)
                        const p4 = getLineIntersect(p4R, p4T)
                        // console.log('ddd p3', p3);
                        // console.log('ddd p4', p4);
                        if (p3 == '' || p4 == '') {
                            console.log('点位有问题!');
                        } else {

                            let pointArr = [
                                startPoint,
                                p3,
                                endPoint,
                                p4
                            ]
                            if (isDrawPolyGon) {

                                const entityPolygon = drawPolyGon(pointArr)
                                polygonEntityArr.push(entityPolygon)
                                isDrawPolyGon = false
                            } else {
                                const points = []
                                pointArr.forEach(item => {
                                    const demo = Cesium.Cartesian3.fromDegrees(item[0], item[1], 0)
                                    points.push(demo)
                                })
                                polygonEntityArr[0].polygon.hierarchy = points
                                // console.log('polygonEntityArr', polygonEntityArr);
                            }
                        }



                    }

                    // 根据点生成点位数据
                    getRectanglePoint([nowPoint[0], nowPoint[1]], [movePosition.longitude, movePosition.latitude])
                }, 100)
            }



        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
        // 鼠标右击事件
        handler.setInputAction((event) => {
            // console.log('ddd event', event);
            if (isDrawLine) {
                // 结束画多边形
                isDrawLine = false
                // 删除鼠标移动画线
                // drawRectangleFunC.delDemoEntity('line_demo_name')
                // 画多边形结束,形成面开始

                // 清空数据
                // 删除画点以及画线
                // drawRectangleFunC.delDemoEntity('line_name')
                drawRectangleFunC.delDemoEntity('point_name')
                nowPoint = []
                polygonEntityArr = []
                pointEntityArr = []

                // console.log('handler',handler);
                // 画框完毕,取消鼠标监听
                handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)//移除事件
                handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)//移除事件
                handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)//移除事件
                // handler.removeAll();
                // console.log('ddd', viewer.entities);
                // console.log('ddd', viewer);

            }


        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)

    },

    // 开始
    klk: () => {
        // drawRectangleFunC.delDemoEntity('point_name')
        drawRectangleFunC.draw()
        isDrawLine = true
        isDrawPolyGon = false
        nowPoint = []
        polygonEntityArr = []
        pointEntityArr = []
    }
}

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

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

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

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现cesium动态绘制矩形,可以使用Cesium的Primitive API和MouseEvents。具体步骤如下: 1. 创建矩形entity并添加到场景中。 ``` var entity = viewer.entities.add({ rectangle: { coordinates: Cesium.Rectangle.fromDegrees(-100.0, 20.0, -90.0, 30.0), material: Cesium.Color.RED.withAlpha(0.5), outline: true, outlineColor: Cesium.Color.BLACK } }); ``` 2. 获鼠标左键按下和移动事件,并更新矩形的坐标。 ``` var startPosition; var mouseHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); mouseHandler.setInputAction(function(movement) { startPosition = movement.position; }, Cesium.ScreenSpaceEventType.LEFT_DOWN); mouseHandler.setInputAction(function(movement) { if (Cesium.defined(startPosition)) { var endPosition = movement.position; var startCartesian = viewer.scene.camera.pickEllipsoid(startPosition, viewer.scene.globe.ellipsoid); var endCartesian = viewer.scene.camera.pickEllipsoid(endPosition, viewer.scene.globe.ellipsoid); if (Cesium.defined(startCartesian) && Cesium.defined(endCartesian)) { var startCartographic = Cesium.Cartographic.fromCartesian(startCartesian); var endCartographic = Cesium.Cartographic.fromCartesian(endCartesian); var west = Math.min(startCartographic.longitude, endCartographic.longitude); var east = Math.max(startCartographic.longitude, endCartographic.longitude); var south = Math.min(startCartographic.latitude, endCartographic.latitude); var north = Math.max(startCartographic.latitude, endCartographic.latitude); entity.rectangle.coordinates = Cesium.Rectangle.fromDegrees(west, south, east, north); } } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); ``` 3. 获鼠标左键松开事件,结束矩形绘制。 ``` mouseHandler.setInputAction(function(movement) { startPosition = undefined; }, Cesium.ScreenSpaceEventType.LEFT_UP); ``` 这样,当用户按下鼠标左键并移动时,就可以动态绘制矩形

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值