使用mapbox自定义绘制工具(point,line,polygon,circle,rectangle)

1 篇文章 1 订阅
1 篇文章 1 订阅

如何使用mapbox绘制常用的工具

许多小伙伴刚接触map的时候,都不知道怎么下手,都是一味埋头网上一顿搜。然后发现别人写的东西自己发现拿过来放在自己的代码中不合适。有些怎么实例化地图都不知道,所以看官网API是非常重要的,一来让你对mapbox一些属性,方法以及事件有一个初步的了解,然后在结合别人写的功能自己才会容易上手。操作地图不外乎就是一些事件,其实mapbox有一些关于绘制工具的一些插件,也可以自己定义绘制工具。
我这里的demo,就是一个很简单的实现。实现(point,line,polygon,circle,rectangle)我用到的事件就三种(click(鼠标单击),mousemove(鼠标移动),dblclick(双击结束),就根据这三个事件做这几个绘制工具。希望对你在网上找关于mapbox绘制工具在逻辑上有一个直观的了解,为了方便参考者一看就懂。所以我把各个功能的代码分开展示。如果想要看本实例效果的自己创建一个html文件把一下代码顺序复制到你所创建的html文件中。直接打开即可,当然这里面的demo可能不完美,参考者可以根据需要自行修改。

需要引入的资源

<script src='https://api.mapbox.com/mapbox-gl-js/v2.0.0/mapbox-gl.js'></script>
    <script src="https://cdn.bootcss.com/Turf.js/5.1.6/turf.js"></script>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

Turf.js用于计算面积,距离使用,

创建div

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>mapbox测量工具</title>
    <link href='https://api.mapbox.com/mapbox-gl-js/v2.0.0/mapbox-gl.css' rel='stylesheet' />
    
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
        .map-legend{
            position:absolute;
            z-index: 5;
        }
        .measure-result {
            background-color: white;
            border-radius: 3px;
            height: 16px;
            line-height: 16px;
            padding: 0 3px;
            font-size: 12px;
            box-shadow: 0 0 0 1px #ccc;
            position: absolute;
        }
        .measure-result .close {
            cursor: pointer;
            width: 14px;
            height: 14px;
            line-height: 16px;
            text-align: center;
            padding: 0;
        }
    </style>
</head>
<body>
    <div id='map'>
        <div class="map-legend">
        <button id="circle"></button>
        <button id="point"></button>
        <button id="line">线</button>
        <button id="polygon">多边形</button>
        <button id="rectangle">矩形</button>
    </div>
    </div>
</body>

引入mapbox实例

  mapboxgl.accessToken = 'pk.eyJ1IjoibGlhbmJvIiwiYSI6ImNrYWRqeXN5ZzAwenYycm9nZ2M5ZDIzMzMifQ.jTm1afxWBB-OxKGp57wjaw';

        var map = new mapboxgl.Map({
            container: 'map',
            maxZoom: 18,
            minZoom: 0,
            zoom: 10,
            center: [109.1699, 45.9719],
            style: 'mapbox://styles/mapbox/streets-v11',
            attributionControl: false
        });

设置circle工具

  //绘制圆形区域的函数
    let createGeoJSONCircle = function(center, radiusInKm, points) {
        if(!points) points = 64;
        var coords = {
            latitude: center[1],
            longitude: center[0]
        };
        var km = radiusInKm;
        var ret = [];
        var distanceX = km/(111.320*Math.cos(coords.latitude*Math.PI/180));
        var distanceY = km/110.574;

        var theta, x, y;
        for(var i=0; i<points; i++) {
            theta = (i/points)*(2*Math.PI);
            x = distanceX*Math.cos(theta);
            y = distanceY*Math.sin(theta);

            ret.push([coords.longitude+x, coords.latitude+y]);
        }
        ret.push(ret[0]);
        // {
        //     "type": "geojson",
        //     "data": {
        //     "type": "FeatureCollection",
        //         "features": [{
        //         "type": "Feature",
        //         "geometry": {
        //             "type": "Polygon",
        //             "coordinates": [ret]
        //         }
        //     }]
        // }
        // };

        return {
            "type": "Feature",
            "geometry": {
                "type": "Polygon",
                "coordinates": [ret]
            }
        };
    };
 
    $("#circle").click(function (e) {
	debugger
        map.getCanvas().style.cursor = 'crosshair';
        e.stopPropagation();
        clearLayerAndSource();
        var isDraws = true;
        // 禁止双击缩放
        map.doubleClickZoom.disable();
        var radius=0;
        var jsonCircle = {
            'type': 'FeatureCollection',
            'features': []
        };
		let _pixelRadius=0;
        var source = map.getSource('circle');
        if(source){
            //map.getSource('circle').setData(jsonCircle);
        }else{
            map.addSource('circle', {
                type: 'geojson',
                data: jsonCircle
            });
            map.addLayer({
                "id": "circle",
                "type": "fill",
                "source": "circle",
                "layout": {
				 },
                "paint": {
				     
                    "fill-color": "#e6205e",
                    "fill-opacity": 0.6,
					//"circle-radius": {
			         //    stops: [
                    //    [0, 0],
			         //    [20, _pixelRadius]],
			         //    base: 2
			         //   },
				    //  "circle-opacity": 0.5,
					// "circle-stroke-width": 1,
					// "circle-color": "#00f",
					// "circle-pitch-alignment": "map"
	            
                }

            });
        }
        var points = [];
        var starCoords=[];
		let isMousemove=false;
		let isFilst=true;
		let filstCoords=[];
        map.on('click', function (_e) {
            if(isDraws){
                starCoords=[];
                starCoords.push(_e.lngLat.lat);
                starCoords.unshift(_e.lngLat.lng);
				if(isFilst){
				  filstCoords=starCoords;
				  isFilst=false
				}
                points.push(starCoords);
                map.getSource('circle').setData(createGeoJSONCircle(starCoords, 0));
				isMousemove=true;
				isDraws=true;
            }
        })
		 var moveCoords=[]
        map.on('mousemove', function (_e) {
            if(isDraws && isMousemove){
			    isDraws=true;
                var centerCoords=[]
            
				moveCoords=[_e.lngLat.lng, _e.lngLat.lat];
                if(filstCoords.length !=0){
                    centerCoords=[(parseFloat(filstCoords[0])+parseFloat(moveCoords[0]))/2,(parseFloat(filstCoords[1])+parseFloat(moveCoords[1]))/2];
                    var _points = [];
					_points.push(moveCoords)
					_points.unshift(filstCoords);
					//points.concat([moveCoords]);
                    var line = turf.lineString(_points);
                    var len = turf.length(line);
                    if(len < 1) {
					     _pixelRadius=len
                        //m
                       // len = Math.round(len * 1000);
                      //  map.getSource('circle').setData(createGeoJSONCircle(filstCoords, len));
                    } else {
                        //km
                        len = len.toFixed(2);
						_pixelRadius=len
                       map.getSource('circle').setData(createGeoJSONCircle(filstCoords, len));
                    }
                }
            }
        })
        map.on('dblclick', function (_e) {
            if(isDraws){
                map.getCanvas().style.cursor = 'grab'
                jsonCircle = {
                    'type': 'FeatureCollection',
                    'features': []
                };
                //map.getSource('circle').setData(jsonCircle);
				isMousemove=false
                isDraws=false;
                map.getCanvas().style.cursor = '';
                var endCoords=[_e.lngLat.lng, _e.lngLat.lat];
                if(filstCoords.length !=0){
				debugger
                    //var _points = points.concat([endCoords]);
					 var _points = [];
					_points.push(moveCoords)
					_points.unshift(filstCoords);
                    var line = turf.lineString(_points);
                    var len = turf.length(line);
                    if(len < 1) {
					   _pixelRadius=len
                      // len = Math.round(len * 1000);
                       // map.getSource('circle').setData(createGeoJSONCircle(filstCoords, len));
                    }else{
                       len = len.toFixed(2);
					   _pixelRadius=len
                       map.getSource('circle').setData(createGeoJSONCircle(filstCoords, len));
                    }
                }
            }

        })

    })

在这里插入图片描述

创建 point 绘制工具

$("#point").click(function (e) {
        map.getCanvas().style.cursor = 'crosshair';
        e.stopPropagation();
        clearLayerAndSource();
        var isDraw = true;
        // 禁止双击缩放
        map.doubleClickZoom.disable();

        var jsonPoint = {
            'type': 'FeatureCollection',
            'features': []
        };
        var source = map.getSource('points');
        if(source) {
            map.getSource('points').setData(jsonPoint);
        }else{
            map.addSource('points', {
                type: 'geojson',
                data: jsonPoint
            });
            map.addLayer({
                id: 'points',
                type: 'circle',
                source: 'points',
                paint: {
                    'circle-color': '#ffffff',
                    'circle-radius': 3,
                    'circle-stroke-width': 2,
                    'circle-stroke-color': '#ff0000'
                }
            });
        }
        var points = [];
        var starCoords=[];
        map.on('click', function (_e) {
            if (isDraw) {
                starCoords=[];
                starCoords.push(_e.lngLat.lat);
                starCoords.unshift(_e.lngLat.lng);
                points.push(starCoords);
            }
        })

        map.on('dblclick', function (_e) {
            if (isDraw) {
                map.getCanvas().style.cursor = 'grab'
                isDraw=false;
                var endCoords=[_e.lngLat.lng, _e.lngLat.lat];
                jsonPoint.features.push({
                    type: 'Feature',
                    geometry: {
                        type: 'Point',
                        coordinates: endCoords
                    }
                });
                map.getSource('points').setData(jsonPoint);
            }
        })

    })

在这里插入图片描述

创建line绘制工具

 $('#line').click(function (e) {
	debugger
        map.getCanvas().style.cursor = 'crosshair';
        e.stopPropagation();
        clearLayerAndSource();
        var isMeasure = true;
        // 禁止双击缩放
        map.doubleClickZoom.disable();
        var jsonPoint = {
            'type': 'FeatureCollection',
            'features': []
        };
        var jsonLine = {
            'type': 'FeatureCollection',
            'features': []
        };
        var markers = [];
        var source = map.getSource('points');
        var lineMoveSource = map.getSource('line-move');
        var lineSource = map.getSource('line');
        if(source) {
            map.getSource('points').setData(jsonPoint);
            if(lineMoveSource){
                map.getSource('line-move').setData(jsonLine);
            }
            if(lineSource){
                map.getSource('line').setData(jsonLine);
            }
        } else {
            map.addSource('points', {
                type: 'geojson',
                data: jsonPoint
            });
            map.addSource('line', {
                type: 'geojson',
                data: jsonLine
            });
            map.addSource('line-move', {
                type: 'geojson',
                data: jsonLine
            });
            map.addLayer({
                id: 'line-move',
                type: 'line',
                source: 'line-move',
                paint: {
                    'line-color': '#ff0000',
                    'line-width': 2,
                    'line-opacity': 0.65
                }
            });
            map.addLayer({
                id: 'line',
                type: 'line',
                source: 'line',
                paint: {
                    'line-color': '#ff0000',
                    'line-width': 2,
                    'line-opacity': 0.65
                }
            });
            map.addLayer({
                id: 'points',
                type: 'circle',
                source: 'points',
                paint: {
                    'circle-color': '#ffffff',
                    'circle-radius': 3,
                    'circle-stroke-width': 2,
                    'circle-stroke-color': '#ff0000'
                }
            });
        }
        function addPoint(coords) {
            if(jsonPoint.features.length > 0) {
                var prev = jsonPoint.features[jsonPoint.features.length - 1];
                jsonLine.features.push({
                    type: 'Feature',
                    geometry: {
                        type: 'LineString',
                        coordinates: [prev.geometry.coordinates, coords]
                    }
                });
                map.getSource('line').setData(jsonLine);
            }
            jsonPoint.features.push({
                type: 'Feature',
                geometry: {
                    type: 'Point',
                    coordinates: coords
                }
            });
            map.getSource('points').setData(jsonPoint);
        }
        map.on('click', function (_e) {
            if(isMeasure) {
                var coords = [_e.lngLat.lng, _e.lngLat.lat];
                addPoint(coords);
                //points.push(coords);
            }
        });
        map.on('mousemove', function (_e) {
            if(isMeasure) {
                var coords = [_e.lngLat.lng, _e.lngLat.lat];
                if (jsonPoint.features.length > 0) {
                    var prev = jsonPoint.features[jsonPoint.features.length - 1];
                    var json = {
                        type: 'Feature',
                        geometry: {
                            type: 'LineString',
                            coordinates: [prev.geometry.coordinates, coords]
                        }
                    };
                    map.getSource('line-move').setData(json);

                }
            }
        });
        map.on('dblclick', function (_e) {
            if(isMeasure) {
                var coords = [_e.lngLat.lng, _e.lngLat.lat];
                addPoint(coords);
                isMeasure = false;
                map.getCanvas().style.cursor = 'grab'
                jsonPoint.features = [];
                jsonLine.features = [];
            }
        });
    });

在这里插入图片描述

创建polygon(多边形)绘制工具

 $('#polygon').click(function (e) {
        map.getCanvas().style.cursor = 'crosshair';
        e.stopPropagation();
        clearLayerAndSource();
        var isMeasure = true;
        // 禁止双击缩放
        map.doubleClickZoom.disable();
        var jsonPoint = {
            'type': 'FeatureCollection',
            'features': []
        };
        var jsonLine = {
            'type': 'FeatureCollection',
            'features': []
        };
        var points = [];
        var source = map.getSource('points-area');
        if(source) {
            map.getSource('points-area').setData(jsonPoint);
            map.getSource('line-area').setData(jsonLine);
        } else {
            map.addSource('points-area', {
                type: 'geojson',
                data: jsonPoint
            });
            map.addSource('line-area', {
                type: 'geojson',
                data: jsonLine
            });
            map.addLayer({
                id: 'line-area',
                type: 'fill',
                source: 'line-area',
                paint: {
                    'fill-color': '#ff0000',
                    'fill-opacity': 0.1
                }
            });
            map.addLayer({
                id: 'line-area-stroke',
                type: 'line',
                source: 'line-area',
                paint: {
                    'line-color': '#ff0000',
                    'line-width': 2,
                    'line-opacity': 0.65
                }
            });
            map.addLayer({
                id: 'points-area',
                type: 'circle',
                source: 'points-area',
                paint: {
                    'circle-color': '#ffffff',
                    'circle-radius': 3,
                    'circle-stroke-width': 2,
                    'circle-stroke-color': '#ff0000'
                }
            });
        }
        function addPoint(coords) {
            jsonPoint.features.push({
                type: 'Feature',
                geometry: {
                    type: 'Point',
                    coordinates: coords
                }
            });
            map.getSource('points-area').setData(jsonPoint);
        }

        map.on('click', function (_e) {
            if(isMeasure) {
                var coords = [_e.lngLat.lng, _e.lngLat.lat];
                points.push(coords);
                addPoint(coords);
            }
        });

        map.on('dblclick', function (_e) {
            if(isMeasure) {
                var coords = [_e.lngLat.lng, _e.lngLat.lat];
                points.push(coords);
                isMeasure = false;
                map.getCanvas().style.cursor = 'grab'
            }
        });

        map.on('mousemove', function (_e) {
            if(isMeasure) {
                var coords = [_e.lngLat.lng, _e.lngLat.lat];
                var len = jsonPoint.features.length;
                if(len != 0 && len !=1){
                    var pts = points.concat([coords]);
                    pts = pts.concat([points[0]]);
                    var json = {
                        type: 'Feature',
                        geometry: {
                            type: 'Polygon',
                            coordinates: [pts]
                        }
                    };
                    map.getSource('line-area').setData(json);
                }
            }
        });
    })

在这里插入图片描述

创建 rectangle(矩形)绘制工具

$("#rectangle").click(function (e) {
	debugger
        map.getCanvas().style.cursor = 'crosshair';
        e.stopPropagation();
        clearLayerAndSource();
        var isDraw = true;
        // 禁止双击缩放
        map.doubleClickZoom.disable();
        var jsonPoint = {
            'type': 'FeatureCollection',
            'features': []
        };
        jsonPoint.features=[];
        var source = map.getSource('rectangle');
        if(source) {
            map.getSource('rectangle').setData(jsonPoint);
        }else{
            map.addSource('rectangle', {
                type: 'geojson',
                data: jsonPoint
            });
            map.addLayer({
                "id": "rectangle",
                "type": "fill",
                "source": "rectangle",
                "layout": {},
                "paint": {
                    "fill-color": "#e6205e",
                    "fill-opacity": 0.6
                }
            });
        }
        var starCoords=[];
		let isMousemove=false;
        map.on('click', function (_e) {
            if (isDraw) {
                starCoords = [_e.lngLat.lng, _e.lngLat.lat];
				isMousemove=true;
            }
        })

        var moveCoords=[];
        map.on('mousemove', function (_e) {
            if (isDraw && isMousemove) {
                moveCoords = [_e.lngLat.lng, _e.lngLat.lat];
                var rightTopCoords=[];
                rightTopCoords=[moveCoords[0],starCoords[1]];
                var buttomLeftCoords=[];
                buttomLeftCoords=[starCoords[0],moveCoords[1]];
                var coords=[];
                coords=[starCoords,rightTopCoords,moveCoords,buttomLeftCoords]
                jsonPoint.features=[];
                jsonPoint.features.push({
                    type: 'Feature',
                    geometry: {
                        type: 'Polygon',
                        coordinates: [coords]
                    }
                });
                map.getSource('rectangle').setData(jsonPoint);
            }
        })

        map.on('dblclick', function (_e) {
		debugger
            if (isDraw) {
			    isMousemove=false;
                isDraw=false;
                map.getCanvas().style.cursor = 'grab'
                var endCoords = [_e.lngLat.lng, _e.lngLat.lat];
                var rightTopCoords=[];
                rightTopCoords=[endCoords[0],starCoords[1]];
                var buttomLeftCoords=[];
                buttomLeftCoords=[starCoords[0],endCoords[1]];
                var coords=[];
                coords=[starCoords,rightTopCoords,endCoords,buttomLeftCoords]
                jsonPoint.features.push({
                    type: 'Feature',
                    geometry: {
                        type: 'Polygon',
                        coordinates: coords
                    }
                });
                map.getSource('rectangle').setData(jsonPoint);
            }
        })
    })

在这里插入图片描述

清除图层(layer)和资源(source)

  //清除draw资源图层
    function clearLayerAndSource(){
        if (map.getLayer('circle')) {
            map.removeLayer('circle')
        }
        if (map.getSource('circle')) {
            map.removeSource('circle');
        }
        if (map.getLayer('points')) {
            map.removeLayer('points')
        }
        if (map.getSource('points')) {
            map.removeSource('points');
        }
        if (map.getLayer('line')) {
            map.removeLayer('line')
        }
        if (map.getSource('line')) {
            map.removeSource('line');
        }
        if (map.getLayer('polygon')) {
            map.removeLayer('polygon')
        }
        if (map.getSource('polygon')) {
            map.removeSource('polygon');
        }
        if (map.getLayer('rectangle')) {
            map.removeLayer('rectangle')
        }
        if (map.getSource('rectangle')) {
            map.removeSource('rectangle');
        }
        if (map.getLayer('line-move')) {
            map.removeLayer('line-move')
        }
        if (map.getSource('line-move')) {
            map.removeSource('line-move');
        }
        if (map.getLayer('points-area')) {
            map.removeLayer('points-area')
        }
        if (map.getSource('points-area')) {
            map.removeSource('points-area');
        }
        if (map.getLayer('line-area-stroke')) {
            map.removeLayer('line-area-stroke')
        }
        if (map.getSource('line-area-stroke')) {
            map.removeSource('line-area-stroke');
        }
        if (map.getLayer('line-area')) {
            map.removeLayer('line-area')
        }
        if (map.getSource('line-area')) {
            map.removeSource('line-area');
        }
    }
	

以上对于有前端基础的小伙伴来说,代码实现逻辑不复杂,如果有疑问,可以加qq(1835334431)
除了以上基础绘制之外,还有如矢量图层(line,polygon,point)在地图上拖拽,编辑,计算面积,测量,数据渲染,数据分析,可以去案例中查看。
1:对了,之前也有小伙伴qq找我,在文章中发现的一些bug,我本地已经修护,只是最近工作上比较忙,文章没有更新,如果需要参考的小伙伴qq联系我,工作期间处于在线状态,随时可以联系,
2:还有一些小伙伴可能在开发中运用了前端框架,什么vue ,svelte等框架,需要集成进去,这不难,我们知道这些框架底层都是js库,转个弯拿过去就可以直接用,实在不知道在框架中怎么使用的,可以联系我,my这边也帮助一些小伙伴也写了一些demo
3: 一下地址是vue2中集成了对mapbox及cesium实现的一些小案例。有兴趣可以参考,有问题欢迎指出。
案例地址:
4,最重要一点,如果文章对你有帮助,给个赞

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值