Cesium实现动态画多边形并测量面积

运行效果

在这里插入图片描述
在这里插入图片描述

知识点

  1. 相比于Cesium实现动态画点、线并测距代码原理是差不多的,我做了一些优化,动态添加标签,而不是在直接写在html中,感觉对性能有一定优化。
  2. 这个代码里我把求面积的注释了,因为没法直接求,需要后端操作连接数据库进行查询。
  3. 查询面积的代码是
    SELECT st_area ( ST_Transform ( ST_GeomFromText (
    	'POLYGON((98.59921 41.20359,117.76853 41.67914,108.01282 28.91936,98.59921 41.20359))',
    	4326), 4527 ) );
    
    其中里面的数组是各个点。
    注意:点要首尾相同,才能构成多边形,求出面积。
  4. 这里面很多点击事件我都没加,可以根据自己需求更改。
  5. 这是使用到的图片素材
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="js/Cesium1.63/Widgets/widgets.css">
    <style>
        #box {
            height: 650px;
            width: 1000px;
        }
        #draw_polygon{
            height: 250px;
            width: 250px;
            background-color: rgba(34, 176, 238, 0.2);
            border-radius: 15px;
            position: absolute;
            z-index: 999;
            left: 20px;
            top: 20px;
        }
        #draw_polygon #draw_polygon_start,#draw_polygon_clear,#draw_polygon_close,#draw_polygon_search{
            height: 35px;
            width: 100px;
            background-color: rgba(255,255,255,0.6);
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            border-radius: 10px;
        }
        #draw_polygon #draw_polygon_start{
            position: absolute;
            top: 10px;
            left: 10px;
        }
        #draw_polygon #draw_polygon_close{
            width: 60px;
            position: absolute;
            top: 200px;
            right: 40px;
        }
        #draw_polygon #draw_polygon_search{
            width: 60px;
            position: absolute;
            top: 200px;
            left: 40px;
        }
        #draw_polygon #draw_polygon_clear{
            position: absolute;
            top: 10px;
            right: 10px;
        }
        #draw_polygon #start,#close,#clear,#search{
            height: 15px;
            width: 15px;
        }
        #draw_polygon #draw_polygon_content{
            width: 200px;
            height: 130px;
            resize: none;
            position: absolute;
            top: 50px;
            left: 20px;
            border-color: rgba(23,81,156,0.3);
            outline: none;
        }
        #draw_polygon #draw_polygon_tip{
            border-radius: 10px;
            height: 70px;
            width: 200px;
            background-color: rgba(204,204,204,.9);
            position: absolute;
            left: 25px;
            top: 90px;
            z-index: 99;
            padding: 2px;
            box-sizing: border-box;
            display: flex;
            flex-direction:column;
            justify-content:center;
        }
        #draw_polygon #draw_polygon_tip_tip{
            font-weight: bolder;
            color: orangered;
        }
        #draw_polygon #draw_polygon_tip_content{
            display: flex;
            justify-content: center;
        }
        #draw_polygon #draw_polygon_tip_choice{
            display: flex;
            justify-content: space-around;
            align-items: center;
        }
        #draw_polygon #draw_polygon_tip_choice span{
            display: inline-block;
            width: 30px;
            line-height: 20px;
            text-align: center;
            border-radius: 10px;
            background-color: orangered;
            cursor: pointer;
        }
        #draw_polygon_toolTip{
            z-index: 600;
            width: 150px;
            line-height: 30px;
            position: absolute;
            background-color: rgba(255, 255, 255, 0.5);
            display: none;
        }
    </style>
</head>
<body>
<div id="box">

</div>
<script src="js/jquery-3.4.1.js"></script>
<script src="js/Cesium1.63/Cesium.js"></script>
<script>
    viewer = new Cesium.Viewer('box', {
        animation:false,
        baseLayerPicker: false,
        geocoder: true,
        timeline: false,
        sceneModePicker: true,
        navigationHelpButton: false,
        useDefaultRenderLoop: true,
        showRenderLoopErrors: true,
        fullscreenButton: true,
        fullscreenElement: 'map3d',
        infoBox: true,
        mapProjection: new Cesium.WebMercatorProjection(),
        imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
            url: "http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=ebf64362215c081f8317203220f133eb",
            layer: "tdtBasicLayer",
            style: "default",
            format: "image/jpeg",
            tileMatrixSetID: "GoogleMapsCompatible",
            show: false,
            maximumLevel: 18
        })
    });
    viewer.scene.globe.depthTestAgainstTerrain = true;//开启地形深度检测,如果鼠标指针和点不重合,这个选项设置为true试试。

    var searchPolygon = function (viewer) {
        var node = '<div id="draw_polygon">\n' +
            '    <div id="draw_polygon_start"><img id="start" src="铅笔.png" alt="">开始绘制</div>\n' +
            '    <div id="draw_polygon_close"><img id="close" src="删除.png" alt="">关闭</div>\n' +
            '    <div id="draw_polygon_tip">\n' +
            '        <div id="draw_polygon_tip_tip">提示:</div>\n' +
            '        <div id="draw_polygon_tip_content"><span id="tip-1">是否查询绘制区域灾害点?</span></div>\n' +
            '        <div id="draw_polygon_tip_choice">\n' +
            '            <span id="draw_polygon_tip_choice_yes">是</span>\n' +
            '            <span id="draw_polygon_tip_choice_no">否</span>\n' +
            '        </div>\n' +
            '    </div>\n' +
            '    <textarea id="draw_polygon_content"></textarea>\n' +
            '    <div id="draw_polygon_clear"><img id="clear" src="橡皮.png" alt="">清除图形</div>\n' +
            '    <div id="draw_polygon_search"><img id="search" src="查询.png" alt="">查询</div>\n' +
            '</div>\n' +
            '<div id="draw_polygon_toolTip"></div>';
        var $parent = $('#box');
        $parent.append(node);
        var $draw = $('#draw_polygon');
        var $tip = $('#draw_polygon_tip');
        var $start = $('#draw_polygon_start');
        var $close = $('#draw_polygon_close');
        var $clear = $('#draw_polygon_clear');
        var $search = $('#draw_polygon_search');
        var $searchYes = $('#draw_polygon_tip_choice_yes');
        var $searchNo = $('#draw_polygon_tip_choice_no');
        var $textarea = $('#draw_polygon_content');
        var $tooltip = $('#draw_polygon_toolTip');
        var contentString = '';
        var activeShapePoints = []; // 所有点坐标
        var activeShape;    // 记录动态图
        var floatingPoint;  // 记录当前鼠标点
        var allDraw = [];	// 记录所有绘制元素
        var allPoint = [];	// 记录所有点
        $tip.hide();
        $draw.slideDown(1000);
        var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
        viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        // 开启地形深度检测 如果点和鼠标不重合,需要设置该属性为true
        viewer.scene.globe.depthTestAgainstTerrain = true;
        function createPoint(worldPosition) {
            var point = viewer.entities.add({
                position: worldPosition,
                point: {
                    color: Cesium.Color.SKYBLUE,
                    pixelSize: 5,
                    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
                }
            });
            allDraw.push(point);
            return point;
        }

        function drawShape(positionData) {
            var shape = viewer.entities.add({
                polygon: {
                    hierarchy: positionData,
                    material: new Cesium.ColorMaterialProperty(Cesium.Color.WHITE.withAlpha(0.7))
                }
            });
            allDraw.push(shape);
            return shape;
        }

        function clearDraw() {
            $.each(allDraw, function (index, value) {
                viewer.entities.remove(value);
            });
            allDraw = [];
        }

        function terminateShape() {
            $tooltip.hide();
            activeShapePoints.pop(); //去除最后一个动态点
            if (activeShapePoints.length) {
                drawShape(activeShapePoints); //绘制最终图
            }
            viewer.entities.remove(floatingPoint); //去除动态点图形(当前鼠标点)
            viewer.entities.remove(activeShape); //去除动态图形
            floatingPoint = undefined;
            activeShape = undefined;
            activeShapePoints = [];
        }

        $start.click(function () {
            handler.setInputAction(function (event) {
                var earthPosition = viewer.scene.pickPosition(event.position);
                if (Cesium.defined(earthPosition)) {
                    var cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(viewer.scene.globe.pick(viewer.scene.camera.getPickRay(event.position), viewer.scene));
                    var lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(7);
                    var lon = Cesium.Math.toDegrees(cartographic.longitude).toFixed(7);
                    allPoint.push({ 'lon': lon, 'lat': lat });
                    contentString = contentString + 'x:' + lat + 'y:' + lon + '\n';
                    $textarea.val(contentString);
                    if (activeShapePoints.length === 0) {
                        floatingPoint = createPoint(earthPosition);
                        activeShapePoints.push(earthPosition);
                        var dynamicPositions = new Cesium.CallbackProperty(function () {
                            return new Cesium.PolygonHierarchy(activeShapePoints);
                        }, false);
                        activeShape = drawShape(dynamicPositions); //绘制动态图
                    }
                    activeShapePoints.push(earthPosition);
                    createPoint(earthPosition);
                }
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            handler.setInputAction(function (event) {
                if (Cesium.defined(floatingPoint)) {
                    var newPosition = viewer.scene.pickPosition(event.endPosition);
                    if (Cesium.defined(newPosition)) {
                        floatingPoint.position.setValue(newPosition);
                        activeShapePoints.pop();
                        activeShapePoints.push(newPosition);
                    }
                    $tooltip.css('left', event.endPosition.x + 45 + "px");
                    $tooltip.css('top', event.endPosition.y - 25 + "px");
                    $tooltip.show();
                    $tooltip.html("请不要重合,右键结束绘制。");
                }
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

            handler.setInputAction(function (event) {
                terminateShape();
                var str = '';
                $.each(allPoint, function (index, value) {
                    str += value.lon + ' ' + value.lat + ',';
                });
                str += allPoint[0].lon + ' ' + allPoint[0].lat;
                //contentString = contentString + '面积:' + GetAreaByPointArr(str).rows[0].st_area + 'm²\n';
                $textarea.val(contentString);
            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
        });

        $close.one('click', function () {
            handler.destroy();
            $textarea.val('');
            clearDraw();
            $draw.remove();

        });

        $clear.click( function () {
            clearDraw();
            $textarea.val('');
            contentString = '';
            activeShapePoints = []; // 所有点坐标
            activeShape;    // 记录动态图
            floatingPoint;  // 记录当前鼠标点
            allDraw = [];
            allPoint = [];
        });

        $search.click(function () {
            $tip.slideDown(500);
        });

        $searchYes.click(function () {
            $tip.slideUp(500);
            $.each(allPoint, function (index, value) {
                // value.lon:经度
                // value.lat:纬度

            })
        });

        $searchNo.click(function () {
            $tip.slideUp(500);
        });
    };
    searchPolygon(viewer);

	function GetAreaByPointArr(str) {
    var area;
    $.ajax({
        url: '/Search/GetAreaByPointArr',
        type: 'post',
        dataType: 'json',
        data: { str: str },
        async: false,
        success: function (response) {
            // 返回面积
            area = response
        },
        error: function () {

        }
    });
    return area;
}

</script>
</body>
</html>
发布了270 篇原创文章 · 获赞 123 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/KaiSarH/article/details/104649665