cesium 实现测距离测面积 (划线画面 跟随鼠标位置 )

效果图
在这里插入图片描述
在这里插入图片描述
方法一:使用插件

cesium_measure.js
下载地址:https://github.com/zhangti0708/cesium-measure/blob/master/src/cesium-measure.js

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/cesium@1.86.0/Build/Cesium/Cesium.js"></script>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cesium@1.86.0/Build/Cesium/Widgets/widgets.css">

    <title>测距&面积</title>
</head>
<style>
    .btn {
        z-index: 999;
        width: 100px;
        height: 30px;
        background-color: #fff;
        position: absolute;
        top: 30px;
        right: 40px;
        line-height: 30px;
        text-align: center;
        user-select: none;
    }
    
    .change {
        z-index: 999;
        width: 100px;
        height: 30px;
        position: absolute;
        top: 30px;
        right: 40px;
        line-height: 30px;
        text-align: center;
        color: #fff;
        background-color: #007acc;
        user-select: none;
    }
    
    .pointInfo {
        z-index: 999;
        position: absolute;
        /* top: 50%;
        left: 50%;
        transform: translate(-50%, -50%); */
        width: 80px;
        height: 40px;
        background-color: #fff;
    }
</style>

<body style="margin: 0;">
    <div id="app">
        <div class="pointInfo" v-show="open" ref="pointinfo" id="point">

        </div>
        <div :class="change?'btn':'change'" @click="signPlace(window.viewer)">
            {{change?"测距":"测面积"}}
        </div>
        <div id="mapcontainer"></div>
    </div>
</body>
<script src="../js/cesium_measure.js"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            plane: [], //存面实例
            pointId: 0,
            change: true,
            open: false,
            openimg: false,
            labelname: '',
            objpoint: {},
            imgs: [
                "../img/0.png",
                "../img/1.png",
                "../img/2.png",
            ],
            urlimg: "../img/0.png",
            point: [], //测距的点
            arr: [], //存放划线的点
            measure: null

        },
        methods: {

            initMap() {
                var viewer = new Cesium.Viewer('mapcontainer', {
                    animation: false, //是否显示动画控件
                    shouldAnimate: true,
                    homeButton: false, //是否显示Home按钮
                    fullscreenButton: true, //是否显示全屏按钮
                    baseLayerPicker: false, //是否显示图层选择控件
                    geocoder: false, //是否显示地名查找控件
                    timeline: false, //是否显示时间线控件
                    sceneModePicker: false, //是否显示投影方式控件
                    navigationHelpButton: false, //是否显示帮助信息控件
                    requestRenderMode: false, //启用请求渲染模式
                    scene3DOnly: false, //每个几何实例将只能以3D渲染以节省GPU内存
                    sceneMode: 3, //初始场景模式 1 2D模式 2 2D循环模式 3 3D模式  Cesium.SceneMode
                    selectionIndicator: false,
                    skyAtmosphere: false,
                    infoBox: false
                });
                viewer._cesiumWidget._creditContainer.style.display = "none";
                this.measure = new Cesium.Measure(viewer);
                return viewer
            },

            mapFlyTo(viewer) {
                viewer.camera.flyTo({
                    destination: new Cesium.Cartesian3.fromDegrees(132.02294829, 53.323929, 180000),
                    duration: 3
                })
            },
            signPlace(viewer) {

                if (this.change) {
                    this.change = false;
                    this.measure.drawLineMeasureGraphics({
                        clampToGround: true,
                        callback: () => {},
                    });
                } else {
                    this.change = true;
                    this.measure.drawAreaMeasureGraphics({
                        clampToGround: true,
                        callback: (e) => {}
                    });
                }
            },


        },
        mounted() {
            window.viewer = this.initMap();
            this.mapFlyTo(window.viewer);
            // this.mapEvent(window.viewer)
        }
    })
</script>

</html>

方法二:自己实现

测面积没实现 ,可以参考方法一插件里的实现方法

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/cesium@1.86.0/Build/Cesium/Cesium.js"></script>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/cesium@1.86.0/Build/Cesium/Widgets/widgets.css">

    <title>测距&面积</title>
</head>
<style>
    .btn {
        z-index: 999;
        width: 100px;
        height: 30px;
        background-color: #fff;
        position: absolute;
        top: 30px;
        right: 40px;
        line-height: 30px;
        text-align: center;
        user-select: none;
    }
    
    .change {
        z-index: 999;
        width: 100px;
        height: 30px;
        position: absolute;
        top: 30px;
        right: 40px;
        line-height: 30px;
        text-align: center;
        color: #fff;
        background-color: #007acc;
        user-select: none;
    }
    
    .pointInfo {
        z-index: 999;
        position: absolute;
        /* top: 50%;
        left: 50%;
        transform: translate(-50%, -50%); */
        width: 80px;
        height: 40px;
        background-color: #fff;
    }
</style>

<body style="margin: 0;">
    <div id="app">
        <div class="pointInfo" v-show="open" ref="pointinfo" id="point">

        </div>
        <div :class="change?'btn':'change'" @click="signPlace(window.viewer)">
            {{change?"测距":"测面积"}}
        </div>
        <div id="mapcontainer"></div>
    </div>
</body>
<script src="../js/cesium_measure.js"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            plane: [], //存面实例
            pointId: 0,
            change: true,
            open: false,
            openimg: false,
            labelname: '',
            objpoint: {},
            imgs: [
                "../img/0.png",
                "../img/1.png",
                "../img/2.png",
            ],
            urlimg: "../img/0.png",
            point: [], //测距的点
            arr: [], //存放划线的点
            measure: null,
            timeline: null

        },
        methods: {
            drawLineMeasureGraphics(viewer) {
                window.that = this
                var draw = new Cesium.CustomDataSource('measureLayer')
                viewer.dataSources.add(draw)
                var positions = [],
                    positions_mian = [],
                    polygon = new Cesium.PolygonHierarchy(),
                    _lineEntity = new Cesium.Entity(),
                    $this = this,
                    lineObj,
                    _handlers = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
                // left
                _handlers.setInputAction((movement) => {
                    var cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
                    // console.log("cli" + cartesian);
                    var cartographic = Cesium.Cartographic.fromCartesian(cartesian, viewer.scene.globe.ellipsoid, new Cesium.Cartographic());
                    var lat = Cesium.Math.toDegrees(cartographic.latitude);
                    var lng = Cesium.Math.toDegrees(cartographic.longitude);
                    var height = cartographic.height;
                    var objpoint = {
                        longitude: lng,
                        latitude: lat
                    }
                    this.point.push(cartesian)
                    if (this.point.length > 1) {
                        var distance = this.disTance(this.point)
                        this.labelname = distance;
                        // this.creatLine(this.arr, viewer)
                    }
                    if (cartesian && cartesian.x) {
                        if (positions.length == 0) {
                            positions.push(cartesian.clone());
                        }
                        this.addpoint(objpoint, viewer)
                        positions.push(cartesian);
                        // 测距
                    }
                }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

                _handlers.setInputAction((movement) => {
                    // console.log(positions);
                    var cartesian = viewer.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);
                    if (positions.length >= 2) {
                        if (cartesian && cartesian.x) {
                            positions.pop();
                            positions.push(cartesian);
                        }
                    }
                }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
                // right
                _handlers.setInputAction((movement) => {

                    _handlers.destroy()
                    _handlers = null
                    let cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
                    var cartographic = Cesium.Cartographic.fromCartesian(cartesian, viewer.scene.globe.ellipsoid, new Cesium.Cartographic());
                    var lat = Cesium.Math.toDegrees(cartographic.latitude);
                    var lng = Cesium.Math.toDegrees(cartographic.longitude);
                    var height = cartographic.height;
                    var objpoint = {
                        longitude: lng,
                        latitude: lat
                    }
                    this.addpoint(objpoint, viewer)
                }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

                _lineEntity.polyline = {
                    width: 5,
                    material: Cesium.Color.BLUE.withAlpha(0.8),
                    clampToGround: false
                }
                _lineEntity.polyline.positions = new Cesium.CallbackProperty(function() {

                    return positions
                }, false)

                lineObj = draw.entities.add(_lineEntity)

            },
            // 测面
            drawplane(viewer) {
                var draw = new Cesium.CustomDataSource('measureLayer1')
                viewer.dataSources.add(draw)
                var positions = [],
                    polygon = new Cesium.PolygonHierarchy(),
                    _polygonEntity = new Cesium.Entity(),
                    polyObj = null,
                    _label = '',
                    _handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
                // left
                _handler.setInputAction((movement) => {
                    var cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
                    if (cartesian && cartesian.x) {
                        if (positions.length == 0) {
                            polygon.positions.push(cartesian.clone())
                            positions.push(cartesian.clone());
                        }
                        positions.push(cartesian.clone());
                        polygon.positions.push(cartesian.clone())

                        // var cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
                        var cartographic = Cesium.Cartographic.fromCartesian(cartesian, viewer.scene.globe.ellipsoid, new Cesium.Cartographic());
                        var lat = Cesium.Math.toDegrees(cartographic.latitude);
                        var lng = Cesium.Math.toDegrees(cartographic.longitude);
                        var height = cartographic.height;
                        var objpoint = {
                            longitude: lng,
                            latitude: lat
                        }
                        this.addpoint(objpoint, viewer)
                        if (!polyObj) {

                            _polygonEntity.polyline = {
                                width: 3,
                                material: Cesium.Color.BLUE.withAlpha(0.8),
                                clampToGround: false
                            }

                            _polygonEntity.polyline.positions = new Cesium.CallbackProperty(function() {
                                return positions
                            }, false)

                            _polygonEntity.polygon = {

                                hierarchy: new Cesium.CallbackProperty(function() {
                                    return polygon
                                }, false),

                                material: Cesium.Color.WHITE.withAlpha(0.8),
                                clampToGround: false
                            }

                            polyObj = draw.entities.add(_polygonEntity)
                        }
                    }
                }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
                // mouse
                _handler.setInputAction((movement) => {

                    var cartesian = viewer.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);
                    // var cartesian = $this._viewer.scene.camera.pickEllipsoid(movement.endPosition, $this._viewer.scene.globe.ellipsoid);
                    if (positions.length >= 2) {
                        if (cartesian && cartesian.x) {
                            positions.pop()
                            positions.push(cartesian);
                            polygon.positions.pop()
                            polygon.positions.push(cartesian);
                        }
                    }
                }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

                // right
                _handler.setInputAction((movement) => {
                    let cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);

                    _handler.destroy();

                    positions.push(positions[0]);

                    // let cartesian = viewer.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
                    var cartographic = Cesium.Cartographic.fromCartesian(cartesian, viewer.scene.globe.ellipsoid, new Cesium.Cartographic());
                    var lat = Cesium.Math.toDegrees(cartographic.latitude);
                    var lng = Cesium.Math.toDegrees(cartographic.longitude);
                    var height = cartographic.height;
                    var objpoint = {
                        longitude: lng,
                        latitude: lat
                    }
                    this.addpoint(objpoint, viewer)
                        // if (typeof options.callback === 'function') {

                    //     options.callback($this.transformCartesianArrayToWGS84Array(positions), polyObj);
                    // }
                }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);


            },
            initMap() {
                var viewer = new Cesium.Viewer('mapcontainer', {
                    animation: false, //是否显示动画控件
                    shouldAnimate: true,
                    homeButton: false, //是否显示Home按钮
                    fullscreenButton: true, //是否显示全屏按钮
                    baseLayerPicker: false, //是否显示图层选择控件
                    geocoder: false, //是否显示地名查找控件
                    timeline: false, //是否显示时间线控件
                    sceneModePicker: false, //是否显示投影方式控件
                    navigationHelpButton: false, //是否显示帮助信息控件
                    requestRenderMode: false, //启用请求渲染模式
                    scene3DOnly: false, //每个几何实例将只能以3D渲染以节省GPU内存
                    sceneMode: 3, //初始场景模式 1 2D模式 2 2D循环模式 3 3D模式  Cesium.SceneMode
                    selectionIndicator: false,
                    skyAtmosphere: false,
                    infoBox: false
                });
                viewer._cesiumWidget._creditContainer.style.display = "none";
                this.measure = new Cesium.Measure(viewer);
                return viewer
            },

            mapFlyTo(viewer) {
                viewer.camera.flyTo({
                    destination: new Cesium.Cartesian3.fromDegrees(132.02294829, 53.323929, 180000),
                    duration: 3
                })
            },

            signPlace(viewer) {
                viewer.screenSpaceEventHandler.destroy()
                this.point = [];
                this.labelname = ""

                if (this.change) {
                    this.change = false;
                    this.drawLineMeasureGraphics(viewer)
                } else {
                    this.change = true;
                    this.drawplane(viewer)
                }
            },
            // 两点距离
            //positions 包含两个点的数组
            disTance(positions) {
                var distance = 0;
                for (var i = 0; i < positions.length - 1; i++) {

                    var point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
                    var point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1]);
                    // console.log(point1cartographic, point2cartographic);

                    var geodesic = new Cesium.EllipsoidGeodesic();
                    geodesic.setEndPoints(point1cartographic, point2cartographic);
                    var s = geodesic.surfaceDistance;

                    distance = distance + s;
                }
                return distance.toFixed(0);
            },

            /**
             * 计算一组坐标组成多边形的面积
             * @param {*} positions 
             */
            getPositionsArea: function(positions) {
                let result = 0
                if (positions) {
                    let h = 0
                    let ellipsoid = Cesium.Ellipsoid.WGS84
                    positions.push(positions[0])
                    for (let i = 1; i < positions.length; i++) {
                        let oel = ellipsoid.cartographicToCartesian(
                            this.transformWGS84ToCartographic(positions[i - 1])
                        )
                        let el = ellipsoid.cartographicToCartesian(
                            this.transformWGS84ToCartographic(positions[i])
                        )
                        h += oel.x * el.y - el.x * oel.y
                    }
                    result = Math.abs(h).toFixed(2)
                }
                return result
            },

            // 添加点
            //添加图标点
            addpoint(pointData, viewer) {

                var billboards = viewer.scene.primitives.add(new Cesium.BillboardCollection());
                window.billboards = billboards;
                var labels = viewer.scene.primitives.add(new Cesium.LabelCollection());
                window.labels = labels
                position = Cesium.Cartesian3.fromDegrees(pointData.longitude, pointData.latitude,
                    0);

                billboards.add({
                    id: this.pointId,
                    position: position,
                    image: this.urlimg,
                    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                });
                labels.add({
                    show: !this.change,
                    position: position,
                    text: this.labelname,
                    id: this.pointId,
                    font: '10px',
                    pixelOffset: new Cesium.Cartesian2(-20, -30),
                })
                this.pointId++;


            },

            //面
            creatplane(polylineData, viewer) {
                var entit = this.plane[0]
                this.plane = [];
                viewer.entities.remove(entit);
                var polyon = viewer.entities.add({
                    polygon: {
                        // 获取指定属性(positions,holes(图形内需要挖空的区域))
                        hierarchy: {
                            positions: Cesium.Cartesian3.fromDegreesArray(polylineData)
                        },
                        // 边框
                        outline: true,
                        // 边框颜色
                        outlineColor: Cesium.Color.WHITE,
                        // 边框尺寸
                        outlineWidth: 2,
                        // 填充的颜色,withAlpha透明度
                        material: Cesium.Color.GREEN.withAlpha(0.5),
                        // 是否被提供的材质填充
                        fill: true,
                        // 显示在距相机的距离处的属性,多少区间内是可以显示的
                        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(1000, 10000000),
                        // 是否显示
                        show: true,
                        // 顺序,仅当`clampToGround`为true并且支持地形上的折线时才有效。
                        zIndex: 10
                    }
                })
                this.plane.push(polyon)
            },
            mapEvent(viewer) {
                // var mapEvent = new Cesium.ScreenSpaceEventHandler(cesiumScene.canvas);
                viewer.screenSpaceEventHandler.setInputAction((click) => {
                    var pick = viewer.scene.pick(click.endPosition);
                    if (pick && typeof(pick.id) == "number") {
                        document.body.style = "cursor: pointer;";
                        this.infobox(viewer.scene, viewer)
                    } else {
                        document.body.style = "cursor: default;";
                    }
                }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
            },


            //弹框位置
            htmlFixed(cesiumView, htmlOverlay, lng, lat) {
                const domHeight = htmlOverlay.offsetHeight; // DOM的高度
                const domWidth = htmlOverlay.offsetWidth; // DOM的宽度
                const heightOffset = 20; // Y轴偏移量
                const widthOffset = -9; // X轴偏移量

                const scratch = new Cesium.Cartesian2();
                cesiumView.scene.preRender.addEventListener(function() {
                    var las = lat - 0.0009;
                    let position = Cesium.Cartesian3.fromDegrees(
                        lng, las, 2);
                    let canvasPosition = cesiumView.scene
                        .cartesianToCanvasCoordinates(position,
                            scratch);
                    if (Cesium.defined(canvasPosition)) {
                        htmlOverlay.style.top = canvasPosition.y -
                            domHeight -
                            heightOffset + 'px';
                        htmlOverlay.style.left = canvasPosition.x -
                            domWidth / 2 -
                            widthOffset + 'px';
                    }
                });
            },

        },
        mounted() {
            window.viewer = this.initMap();
            this.mapFlyTo(window.viewer);
            // this.mapEvent(window.viewer)
        }
    })
</script>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LBY_XK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值