Mapbox实现点图层多点拖动、标记点标记效果
现通过监听地图的点击、鼠标移动和鼠标松开事件来实现拖拽操作,根据事件的发生情况更新标记点的位置,并提供了添加新点和取消编辑的功能。
效果视频链接:https://live.csdn.net/v/381248
实现思路:
构造函数:构造函数接受地图对象 map、图层ID layerID 和属性 xzData,并初始化类的属性。
edit 方法:该方法用于开始编辑标记点。在鼠标移动事件处理程序中,如果正在拖动且已选择特征,则更新选定特征的坐标。在鼠标松开事件处理程序中,如果正在拖动且已选择特征,则将 isDragging 设置为 false,表示拖动结束。
getSelectedFeatureIndex 方法:该方法接受一个选定的特征对象,并返回该特征在特征数组中的索引。
updateFeaturePosition 方法:该方法接受一个特征索引 index 和新的坐标 newCoordinates,并更新该索引对应特征的坐标为新坐标。
cancelEdit 方法:该方法用于取消编辑操作。它会将正在拖动标记点的状态重置为初始状态,恢复标记点的位置到初始状态,并移除事件监听器。
addNewPoint 方法:该方法接受新的经纬度坐标 lngLat,并在特征数组中添加一个新的点特征,然后更新地图上的数据源。
相关代码
调用封装的构造类
// 图层合集
addLayers() {
this.layers = {
Pit3DgcbwdData: new Pit3DgcbwdDataLayer(),
heatMap: new HeatMapLayer(),
dragMarker:new DragMarker(this.map, "pit3DgcbwdData", "xz")
};
},
//开始编辑
edit(data,type) {
let dataJson=JSON.parse(JSON.stringify(this.json))
let index=null
for (let i = 0; i < dataJson.features.length; i++) {
if (dataJson.features[i].properties.name == data.properties.name) {
index = i;
}
}
if(type==1){
dataJson.features[index].properties["xz"] = 1;
this.layers.dragMarker.edit(dataJson);
// 在拖动操作完成后获取坐标值
this.map.on("mouseup", () => {
console.log("打印拖动后的坐标", this.layers.dragMarker.xy);
});
}else{
dataJson.features[index].properties["editID"] = 0;
this.layers.dragMarker.edit(dataJson);
}
},
构造类
class DragMarker {
constructor(map, layerID,xzData) {
this.map = map;
this.layerID = layerID;
this.featuresArray = null;
this.xzData = xzData;
this.xy = "";
this.selectedFeatureIndex = null;
this.initialCoordinates = null;
this.isDragging = false;
}
edit(featuresA) {
let that = this;
let featuresArray=this.featuresArray
if(featuresA){
featuresArray=featuresA
this.featuresArray=featuresA
}
this.map.getSource(this.layerID).setData(featuresArray);
this.map.on("click", function (e) {
var features = that.map.queryRenderedFeatures(e.point, {});
if (features.length > 0 && features[0].properties[that.xzData] == 1) {
var selectedFeature = features[0];
that.selectedFeatureIndex = that.getSelectedFeatureIndex(selectedFeature);
if (that.selectedFeatureIndex !== null) {
that.initialCoordinates = selectedFeature.geometry.coordinates;
that.isDragging = true;
}
} else {
that.cancelEdit();
}
});
this.map.on("mousemove", function (e) {
if (that.isDragging && that.selectedFeatureIndex !== null) {
var newCoordinates = that.map.unproject(e.point);
that.updateFeaturePosition(that.selectedFeatureIndex, newCoordinates);
}
});
this.map.on("mouseup", function (e) {
if (that.isDragging && that.selectedFeatureIndex !== null) {
that.isDragging = false;
that.initialCoordinates = null;
}
});
}
getSelectedFeatureIndex(selectedFeature) {
const selectedId = selectedFeature.properties.id;
for (let i = 0; i < this.featuresArray.features.length; i++) {
if (this.featuresArray.features[i].properties.id === selectedId) {
return i;
}
}
return null;
}
updateFeaturePosition(index, newCoordinates) {
this.featuresArray.features[index].geometry.coordinates = [newCoordinates.lng, newCoordinates.lat];
this.map.getSource(this.layerID).setData(this.featuresArray);
this.xy = newCoordinates.lng + "," + newCoordinates.lat;
}
cancelEdit() {
// 恢复标记点位置到初始状态
if (this.selectedFeatureIndex !== null && this.initialCoordinates !== null) {
this.featuresArray.features[this.selectedFeatureIndex].geometry.coordinates = this.initialCoordinates;
this.map.getSource(this.layerID).setData(this.featuresArray);
}
this.isDragging = false;
this.selectedFeatureIndex = null;
this.initialCoordinates = null;
// 移除事件监听器
this.map.off("click");
this.map.off("mousemove");
this.map.off("mouseup");
}
addNewPoint(lngLat) {
const newFeature = {
type: 'Feature',
properties: {
},
geometry: {
type: 'Point',
coordinates: [lngLat.lng, lngLat.lat]
}
};
this.featuresArray.features.push(newFeature);
this.map.getSource(this.layerID).setData(this.featuresArray);
}
}
export default DragMarker;