mapboxGL测量实现
2020-04-21 本文已影响0人
牛老师讲webgis
概述
讲真,MapboxGL里面虽然有测量的功能,但是不太好用,于是就萌生了自己实现的方法。本文几个turf.js来说说mapboxGL中测量的实现。
效果
测距 测面实现
1、实现思路
- 按照绘制的流程,需要涉及到map的三个事件:click,dblclick,mousemove,其中click为绘制,dblclick为结束绘制,mousemove为绘制中。这样,定义一个状态标识
isMeasure
,在点击开始绘制的按钮的时候,将标识设置为true
,在map的三个事件中都会根据这个标识判断是否为绘制状态。 - 地图的展示分layer和marker来分别展示;
- layer里面区分点和线(面)图层,以达到比较好的展示效果。
2、实现代码
1.样式
.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;
&.close {
cursor: pointer;
width: 14px;
height: 14px;
line-height: 16px;
text-align: center;
padding: 0;
}
}
2.测量距离
function measureLength() {
var isMeasure = true;
// 禁止双击缩放
map.doubleClickZoom.disable();
map.getCanvas().style.cursor = 'default';
function clearMeasure() {
$(".measure-result").remove();
var source = map.getSource('points');
var json = {
'type': 'FeatureCollection',
'features': []
};
if(source) {
map.getSource('points').setData(json);
map.getSource('line-move').setData(json);
map.getSource('line').setData(json);
}
var sourceArea = map.getSource('points-area');
if(sourceArea) {
map.getSource('points-area').setData(json);
map.getSource('line-area').setData(json);
}
}
clearMeasure();
var jsonPoint = {
'type': 'FeatureCollection',
'features': []
};
var jsonLine = {
'type': 'FeatureCollection',
'features': []
};
var points = [];
const ele = document.createElement('div');
ele.setAttribute('class', 'measure-result');
const option = {
element: ele,
anchor: 'left',
offset: [8, 0]
};
var tooltip = new mapboxgl.Marker(option)
.setLngLat([0, 0])
.addTo(map);
var markers = [];
var source = map.getSource('points');
if(source) {
map.getSource('points').setData(jsonPoint);
map.getSource('line-move').setData(jsonLine);
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);
}
function getLength(coords) {
var _points = points.concat([coords]);
var line = turf.lineString(_points);
var len = turf.length(line);
if(len < 1) {
len = Math.round(len * 1000) + 'm';
} else {
len = len.toFixed(2) + 'km';
}
return len;
}
function addMeasureRes(coords) {
const ele = document.createElement('div');
ele.setAttribute('class', 'measure-result');
const option = {
element: ele,
anchor: 'left',
offset: [8, 0]
};
ele.innerHTML = points.length === 0 ? '起点' : getLength(coords);
var marker = new mapboxgl.Marker(option)
.setLngLat(coords)
.addTo(map);
markers.push(marker);
}
map.on('click', function (_e) {
if(isMeasure) {
var coords = [_e.lngLat.lng, _e.lngLat.lat];
addMeasureRes(coords);
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);
ele.innerHTML = getLength(coords);
} else {
ele.innerHTML = '点击地图开始测量';
}
tooltip.setLngLat(coords);
}
});
map.on('dblclick', function (_e) {
if(isMeasure) {
var coords = [_e.lngLat.lng, _e.lngLat.lat];
addPoint(coords);
isMeasure = false;
map.getCanvas().style.cursor = '';
jsonPoint.features = [];
jsonLine.features = [];
tooltip.remove();
// 添加关闭按钮
const ele = document.createElement('div');
ele.setAttribute('class', 'measure-result close');
const option = {
element: ele,
anchor: 'bottom-left',
offset: [-5, -10]
};
ele.innerHTML = '×';
new mapboxgl.Marker(option)
.setLngLat(coords)
.addTo(map);
ele.onclick = function (__e) {
__e.stopPropagation();
map.doubleClickZoom.enable();
clearMeasure();
}
}
});
}
3.测量面积
function measureArea() {
var isMeasure = true;
// 禁止双击缩放
map.doubleClickZoom.disable();
map.getCanvas().style.cursor = 'default';
function clearMeasure() {
$(".measure-result").remove();
var source = map.getSource('points');
var json = {
'type': 'FeatureCollection',
'features': []
};
if(source) {
map.getSource('points').setData(json);
map.getSource('line-move').setData(json);
map.getSource('line').setData(json);
}
var sourceArea = map.getSource('points-area');
if(sourceArea) {
map.getSource('points-area').setData(json);
map.getSource('line-area').setData(json);
}
}
clearMeasure();
var jsonPoint = {
'type': 'FeatureCollection',
'features': []
};
var jsonLine = {
'type': 'FeatureCollection',
'features': []
};
var points = [];
var ele = document.createElement('div');
ele.setAttribute('class', 'measure-result');
const option = {
element: ele,
anchor: 'left',
offset: [8, 0]
};
var tooltip = new mapboxgl.Marker(option)
.setLngLat([0, 0])
.addTo(map);
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 getArea(coords) {
var pts = points.concat([coords]);
pts = pts.concat([points[0]]);
var polygon = turf.polygon([pts]);
var area = turf.area(polygon);
if(area < 1000) {
area = Math.round(area) + 'm²';
} else {
area = (area / 1000000).toFixed(2) + 'km²';
}
return area;
}
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;
ele.innerHTML = getArea(coords);
tooltip.setLngLat(coords);
// 添加关闭按钮
var _ele = document.createElement('div');
_ele.setAttribute('class', 'measure-result close');
var option = {
element: _ele,
anchor: 'bottom-left',
offset: [-5, -10]
};
_ele.innerHTML = '×';
new mapboxgl.Marker(option)
.setLngLat(coords)
.addTo(map);
_ele.onclick = function (__e) {
__e.stopPropagation();
map.doubleClickZoom.enable();
clearMeasure();
}
}
});
map.on('mousemove', function (_e) {
if(isMeasure) {
var coords = [_e.lngLat.lng, _e.lngLat.lat];
var len = jsonPoint.features.length;
if (len === 0) {
ele.innerHTML = '点击地图开始测量';
} else if (len ===1) {
ele.innerHTML = '点击地图继续绘制';
} else {
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);
ele.innerHTML = getArea(coords);
}
tooltip.setLngLat(coords);
}
});
}
技术博客
CSDN:http://blog.csdn.NET/gisshixisheng
联系方式
类型 | 内容 |
---|---|
1004740957 | |
公众号 | lzugis15 |
niujp08@qq.com | |
webgis群 | 452117357 |