前言
在前一篇文章已经实现了几何对象的绘制(绘制几何对象),那么接下来进行量测就比较容易实现了。具体就三个事件,一个鼠标单击事件,一个鼠标移动事件,一个双击关闭事件,通过前两个事件获取到坐标集,然后对坐标集进行操作。在leaflet中距离量测可以通过调用map对象的distance方法来实现,面积量测可以通过leaflet的量测插件或者第三方库来完成,如果是一句超图的API开发,也可以调用超图的接口实现。
地图事件应该写为方法的形式,不然关闭绘制事件的时候会关闭整个地图事件
一. 距离量测
distance(latlng1,latlng2) 通过传入两个坐标点进行量测,这里的实现思路如下
(1)当只有一个坐标点时,传入第一个坐标和鼠标移动的坐标进行计算,得到第一段动态距离,记为 d1
(2)当有两个坐标点时,传入第一个和第二个坐标点进行量算,得到第一段固定距离,记为 d2
(3)当超过两个坐标点时,传入最后两个坐标点进行量算,得到最后一段距离,记为 d3,并且与之前的距离 d2 相加得到 d4, 即 d4 = d2 + d3
(4)最后,将 d4 与动态距离 d1相加,即可得到整个路径的动态距离
measureDistance() {
this.isMeasureDistance = !this.isMeasureDistance;
if (window._map) {
this.map = window._map;
// 关闭地图双击事件
this.map.doubleClickZoom.disable();
}
const latlngs = [];
// circle 样式
const circleOption = {
radius: 10,
fill: true,
color: "yellow",
weight: 3.5, // 边线宽度:单位像素值
opacity: 1, // 边线透明度
fillColor: "yellow",
fillOpacity: 1 // 最好设置透明度,默认值0.2
};
// 线段样式
const polylineOption = {
stroke: true, // 开启路径追踪,默认为true
color: "yellow"
};
// 绘制线段
const polyline = L.polyline(latlngs, polylineOption);
// 临时线段
const tempLine = L.polyline([], polylineOption);
const onClick = evt => {
latlngs.push([evt.latlng.lat, evt.latlng.lng]);
const circle = L.circle(evt.latlng, circleOption);
circle.addTo(this.map);
polyline.addLatLng(evt.latlng);
polyline.addTo(this.map);
if (latlngs.length === 1) {
this.distance = this.tempDistance;
}
if (latlngs.length === 2) {
this.distance = this.map.distance(latlngs[0], latlngs[1]);
}
if (latlngs.length > 2) {
this.distance += this.map.distance(
latlngs[latlngs.length - 2],
latlngs[latlngs.length - 1]
);
}
};
this.map.on("click", onClick);
const onMouseMove = evt => {
// 至少有一个点才添加临时线段
if (latlngs.length > 0) {
// 添加临时线段
const coords = [
latlngs[latlngs.length - 1],
[evt.latlng.lat, evt.latlng.lng]
];
tempLine.setLatLngs(coords);
this.map.addLayer(tempLine);
}
if (latlngs.length == 1) {
this.tempDistance = this.map.distance(latlngs[0], evt.latlng);
}
if (latlngs.length > 1) {
this.tempDistance = this.map.distance(
latlngs[latlngs.length - 1],
evt.latlng
);
}
};
this.map.on("mousemove", onMouseMove);
// 双击结束绘制
this.map.on("dblclick", () => {
// 关闭单击事件
this.map.off({ click: onClick, mousemove: onMouseMove });
this.setCursor("pointer");
// 开启双击事件
this.map.doubleClickZoom.enable();
});
},
二. 面积量测
面积量测这里我就调用第三方库 turf 来实现了(面积测量貌似有点复杂!) 直接将面的geoJSON格式传递给 turf 对象就行
注意 : turf 应以这样的方式引入 import * as turf from "@turf/turf"
measureArea() {
this.isMeasureArea = !this.isMeasureArea;
if (window._map) {
this.map = window._map;
// 关闭地图双击事件
this.map.doubleClickZoom.disable();
}
const latlngs = [];
// circle 样式
const circleOption = {
radius: 10,
fill: true,
color: "yellow",
weight: 3.5, // 边线宽度:单位像素值
opacity: 1, // 边线透明度
fillColor: "yellow",
fillOpacity: 1 // 最好设置透明度,默认值0.2
};
// 线段样式
const polylineOption = {
stroke: true, // 开启路径追踪,默认为true
color: "yellow"
};
const polyline = L.polyline(latlngs, polylineOption);
const tempLine = L.polyline([], polylineOption);
const polygon = L.polygon(latlngs, polylineOption);
const onClick = evt => {
latlngs.push([evt.latlng.lat, evt.latlng.lng]);
L.circle(evt.latlng, circleOption).addTo(this.map);
polyline.addLatLng(evt.latlng);
polyline.addTo(this.map);
polygon.addLatLng(evt.latlng);
polygon.addTo(this.map);
};
this.map.on("click", onClick);
const onMouseMove = evt => {
// 至少有一个点才添加临时线段
if (latlngs.length > 0) {
//面的临时线段坐标顺序[起点,鼠标移动点,最后一次点击点]
tempLine.setLatLngs([
latlngs[0],
evt.latlng,
latlngs[latlngs.length - 1]
]);
//tempLine.setLatLngs([[latlngs[0],]])
tempLine.addTo(this.map);
polygon.setLatLngs([...latlngs, evt.latlng]);
// 测量面积
this.area = turf.area(polygon.toGeoJSON());
}
};
this.map.on("mousemove", onMouseMove);
this.map.on("dblclick", () => {
// 关闭单击事件
this.map.off({ click: onClick, mousemove: onMouseMove });
this.setCursor("pointer");
// 开启双击事件
this.map.doubleClickZoom.enable();
});
},
三、页面展示
欢迎大家关注我的公众号,我也会在公众号同步更新。
若大家对进阶打怪有兴趣的话,欢迎订阅以下专栏
项目地址,请查阅
地址:leaflet-app