参考地点云,只实时渲染拖动点与前后点的虚线
<template>
<div>
<LPolyline
ref="polyline"
@ready="ready"
:lat-lngs="latlngs"
:color="color"
></LPolyline>
<!-- 编辑线 -->
<LPolyline dashArray="8" :lat-lngs="tempLine" />
</div>
</template>
<script>
import L from "leaflet";
import { LPolyline } from "vue2-leaflet";
import { throttle } from "lodash";
const findDeepMarkerIndex = (arr, marker) => {
let result;
const run = (path) => (v, i) => {
const iRes = path.concat(i);
if (v._leaflet_id === marker._leaflet_id) {
result = iRes;
return true;
}
return Array.isArray(v) && v.some(run(iRes));
};
arr.some(run([]));
let returnVal = {};
if (result) {
returnVal = {
indexPath: result,
index: result[result.length - 1],
parentPath: result.slice(0, result.length - 1),
};
}
return returnVal;
};
var icon = L.divIcon({
className: "my-div-icon",
iconAnchor: [8, 8],
iconSize: [14, 14],
});
export default {
components: {
LPolyline,
},
props: {
latlngs: {},
map: {},
color: {
default: "green",
},
},
data() {
return {
markerGroup: null,
currentIndex: -1,
currentLatlng: null,
// 所有顶点
markers: [],
// 缓存所有编辑点
markerCache: [],
isReady: false,
};
},
computed: {
tempLine() {
if (this.currentIndex < 0) return [];
const len = this.latlngs.length;
const preIndex = this.currentIndex - 1;
const nextIndex = this.currentIndex + 1;
const line = [this.currentLatlng];
if (preIndex > -1) {
line.unshift(this.latlngs[preIndex]);
}
if (nextIndex < len) {
line.push(this.latlngs[nextIndex]);
}
return line;
},
},
methods: {
ready() {
this.initMarkers();
this.isReady = true;
},
initMarkers() {
const coordsArr = this.$refs.polyline.mapObject.getLatLngs();
this.markers = coordsArr.map(this.createMarker);
this.filterMarkerGroup();
this.map.on("mousemove", this.applyLimitFilters, this);
// 首次制作时过滤
this.applyLimitFilters({});
this.map.addLayer(this.markerGroup);
},
createMarker(latlng) {
const marker = new L.Marker(latlng, {
draggable: true,
icon,
});
marker._pmTempLayer = true;
this.markerGroup.addLayer(marker);
// 监听拖拽事件
marker.on("move", this.onMarkerDrag, this);
marker.on("dragend", this.onMarkerDragEnd, this);
return marker;
},
filterMarkerGroup() {
this.markerCache = [];
const allMarkers = [...this.markerGroup.getLayers()];
this.markerCache = allMarkers.filter((v, i, s) => s.indexOf(v) === i);
},
applyLimitFilters: throttle(function ({ latlng = { lat: 0, lng: 0 } }) {
const makersNearCursor = this.filterClosestMarkers(latlng);
const markersToAdd = [...makersNearCursor];
this.renderLimits(markersToAdd);
}, 200),
filterClosestMarkers(latlng) {
const markers = [...this.markerCache];
const limit = 3;
if (limit === -1) {
return markers;
}
markers.sort((l, t) => {
const distanceA = l._latlng.distanceTo(latlng);
const distanceB = t._latlng.distanceTo(latlng);
return distanceA - distanceB;
});
const closest = markers.filter((l, i) => (limit > -1 ? i < limit : true));
return closest;
},
renderLimits(markers) {
this.markerCache.forEach((l) => {
if (markers.includes(l)) {
this.markerGroup.addLayer(l);
} else {
this.markerGroup.removeLayer(l);
}
});
},
onMarkerDrag(e) {
const { index } = findDeepMarkerIndex(this.markers, e.target);
this.currentIndex = index;
this.currentLatlng = [e.latlng.lat, e.latlng.lng];
},
onMarkerDragEnd() {
const preIndex = this.currentIndex;
this.currentIndex = -1;
const polyline = JSON.parse(JSON.stringify(this.latlngs));
polyline[preIndex] = [...this.currentLatlng];
this.$emit("change", polyline);
},
},
watch: {
latlngs: {
immediate: true,
handler() {
if (this.markerGroup) {
this.markerGroup.clearLayers();
}
this.markerGroup = new L.FeatureGroup();
this.markerGroup._pmTempLayer = true;
if (this.isReady) {
setTimeout(() => {
this.initMarkers();
}, 5);
}
},
},
},
};
</script>
使用: