当前位置: 代码迷 >> 综合 >> mapbox gl结合turf.js完成绘图工具画线等距平分
  详细解决方案

mapbox gl结合turf.js完成绘图工具画线等距平分

热度:32   发布时间:2023-12-21 13:27:43.0

1.首先引入对应的sdk插件,以及页面元素,代码如下:

<link href="https://api.mapbox.com/mapbox-gl-js/v2.2.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.2.0/mapbox-gl.js"></script>
<script src="js/mapbox-gl-draw.js"></script>
<link rel="stylesheet"href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.2.2/mapbox-gl-draw.css" type="text/css"><!-- 使用unpkg -->
<script src="https://unpkg.com/@turf/turf/turf.min.js"></script><div id="map"></div>
<button id="drawLine" onclick="drawLine()">绘线</button>

2.初始化地图,代码如下:

            mapboxgl.accessToken = '';var map = new mapboxgl.Map({container: 'map', // container idstyle: 'mapbox://styles/mapbox/streets-v11', // style URLcenter: [-74.5, 40], // starting position [lng, lat]zoom: 9 // starting zoom});var draw = new MapboxDraw({displayControlsDefault: false});map.addControl(draw); //添加绘制控件

3.添加绘线的代码: 

let drawLineBool = false;
let pointsNum = 12; //定义点的个数,12个点,平均分成11段
//绘制线function drawLine() {drawLineBool = true;draw.changeMode("draw_line_string"); //绘制线map.on('draw.create', updateArea); //绘制后的回调函数}
//绘制线的回调函数function updateArea(e) {var data = draw.getAll();var ids = draw.add(data);if (data.features.length > 0) {console.log(1, data.features);let lineDisArr = [];let getLen = data.features[0].geometry.coordinates;let arr_bearing = [];for (let d = 0; d < getLen.length; d++) {if (d < getLen.length - 1) {var s1 = turf.point(getLen[d]);var e1 = turf.point(getLen[d + 1]);let point1 = s1.geometry.coordinates;let point2 = e1.geometry.coordinates;//距离判断let twoPointsDis = getDistance(point1, point2);lineDisArr.push(twoPointsDis);arr_bearing.push(getBearing(getLen[d], getLen[d + 1]));}}console.log("每段距离,夹角:", lineDisArr, arr_bearing);var from1_ = turf.point(data.features[0].geometry.coordinates[0]);var to = turf.point(data.features[0].geometry.coordinates[data.features[0].geometry.coordinates.length - 1]);pointRender("from1_", from1_.geometry.coordinates);pointRender("to_", to.geometry.coordinates);if (data.features[0].geometry.coordinates.length == 2) {//绘制的是直线的情况var bearing = turf.bearing(from1_, to);var options = {units: 'miles'};var line_ = turf.lineString(data.features[0].geometry.coordinates);var length_ = turf.length(line_, {units: 'miles'});var distance = length_ / (pointsNum - 1); //分成八个点,有七段let destination_;for (let r = 0; r < pointsNum - 2; r++) {if (destination_) {destination_ = splitLinePoint(destination_.geometry.coordinates, distance, bearing);} else {destination_ = splitLinePoint(from1_.geometry.coordinates, distance, bearing);}pointRender("id_" + r, destination_.geometry.coordinates);}} else if (data.features[0].geometry.coordinates.length > 2) {第一步,算出折线的总长度var line_ = turf.lineString(data.features[0].geometry.coordinates);var length_ = turf.length(line_, {units: 'miles'});第二步,算出每一段的距离长度let distance_ = length_ / (pointsNum - 1); //分成八个点,有七段//第三步,算出前一个点和下一个点之间的夹角let data_ = data.features[0].geometry.coordinates;// const len = data_.length - 1; //折线的点的个数var dest_;let end_2;let count = 0;let totalNum;if (lineDisArr.length > pointsNum) {totalNum = lineDisArr.length;} else {totalNum = pointsNum;}for (let p = 0; p < lineDisArr.length; p++) {if (count < lineDisArr.length - 1) {for (let a = 1; a < totalNum - 1; a++) {//需要在下一条线上绘制点if (lineDisArr[p] - distance_ * a < 0) {if (dest_ && arr_bearing[count]) {var s1 = turf.point(dest_.geometry.coordinates);var e1 = turf.point(getLen[count]);let point1 = s1.geometry.coordinates;let point2 = e1.geometry.coordinates;//距离判断let twoPointsDis = lineDisArr[count] - getDistance(point1, point2);if (distance_ > twoPointsDis && twoPointsDis > 0) {count++;dest_ = splitLinePoint(getLen[count], distance_ - twoPointsDis, arr_bearing[count]);} else {dest_ = splitLinePoint(dest_.geometry.coordinates, distance_, arr_bearing[count]);}} else {if (arr_bearing[count]) {count++;dest_ = splitLinePoint(getLen[count], distance_ * a - lineDisArr[p], arr_bearing[count]);}}pointRender("id_t_" + a, dest_.geometry.coordinates);} else {if (end_2) {end_2 = splitLinePoint(end_2.geometry.coordinates, distance_, arr_bearing[count]);} else {var from1_ = turf.point(getLen[0]);end_2 = splitLinePoint(from1_.geometry.coordinates, distance_, arr_bearing[count]);}pointRender("id_t_y_" + (a), end_2.geometry.coordinates);}}}}}map.on("dblclick", function(e) {draw.changeMode("simple_select"); //直接退出选择模式,进入到简单模式// drawLineBool = false;});}}

4.用到的turf计算的方法:

//计算两点间的夹角function getBearing(point1, point2) {var point_s = turf.point(point1);var point_e = turf.point(point2);return turf.bearing(point_s, point_e);}//计算两点间的距离function getDistance(point1, point2) {var from = turf.point(point1);var to = turf.point(point2);var options = {units: 'miles'};return turf.rhumbDistance(from, to, options);}//计算等距的点,获取目标点function splitLinePoint(point, distance, bearing) {//计算隔多远的目标点位置,取一个点并计算给定的以度、弧度、英里或公里为单位的距离目的地点的位置var point = turf.point(point);var options = {units: 'miles'};var destination = turf.destination(point, distance, bearing, options);// console.log(333, destination, destination.geometry.coordinates);return destination;}

5.添加点样式的函数:

//绘制点function pointRender(id, coordinates) {let geojson = {'type': 'Point','coordinates': coordinates};if (map.getLayer(id)) {map.removeLayer(id)}if (map.getSource('point_' + id)) {map.removeSource('point_' + id);}map.addSource('point_' + id, {'type': 'geojson','data': geojson});map.addLayer({"id": id,"type": "circle","source": 'point_' + id,"paint": {'circle-radius': 5,'circle-color': '#ff0000'},"filter": ['in', '$type', 'Point']});}

效果如如下:

 该折线平分成11段,打点个数12个。