Leaflet - 如何在拖放时匹配标记和折线(单击鼠标的新标记和线)
Leaflet - How to match marker and polyline on drag and drop (new markers and lines with mouse click)
问题:通过在地图上单击并沿着多段线拖动来放置标记,就像丝带一样不起作用。
我有一个类似的项目:
这很好,非常感谢!到 iH8 :-)。
我尝试更上一层楼,成为更大的开源割草机机器人导航项目的一部分:
https://github.com/steger123/Lawn-mower-robot
https://github.com/steger123/Lawn-mower-robot/tree/master/codes/JavaScript/PolyLine
不幸的是,新的(绿色)线没有用标记(像丝带)拉出来。
那么,程序是如何工作的:
- 使用“路由”按钮生成一些 HTML。 - 工作。
- 使用以下代码生成带有初始线(红色)和标记的地图:- 工作。
- 点击“路线”按钮可以通过点击地图在地图上做标记。 - 工作。
- 用蓝线连接标记。 - 工作。
- 再次点击“Rouring”按钮找到路线 - Working。
- 将线条转换为一条绿色折线(稍后必须将此线与新标记一起拖动。)- 工作。
- 所以当我拖动标记时,只有标记在移动,线没有,但是我分配了三个安德勒。
为了更容易找到问题,在 script.js:
中搜索“*”
index.html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin="" />
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin=""></script>
<style>
#fieldMap {
height: 600px;
}
</style>
<title> DRAG Polyline</title>
</head>
<body>
<table style="width:100%">
<tr>
<td>Latitude: <span id="lat"></span></td>
<td>Longitude: <span id="lon"></span></td>
</tr>
<tr>
<td> <span id="client"></span></td>
<td><span id="screen"></span></td>
</tr>
<tr>
<td> <button id="myRouting" onclick="btnRouting()">Routing</button></td>
<td><button id="myRoutSave" onclick="myRoutSave()">Save Route</button></td>
</tr>
<tr>
<td> <button id="myRoutLoad" onclick="myRoutLoad()">Load Route</button></td>
<td><button id="myRoutSend" onclick="myRoutSend()">Send Route</button></td>
</tr>
</table>
<div id="fieldMap"></div>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
script.js:
const map = L.map('fieldMap').setView([28.4588446, 77.2867589], 17); //The initial point
var layer = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
map.addLayer(layer); // Adding layer to the map
var marker_arr = [];
var marker_pos = [];
var marker_new = [];
///////////////////
// ADD markers :
//var a = new L.LatLng(28.4588446, 77.2867589),
// b = new L.LatLng(28.4578446, 77.2867589),
// c = new L.LatLng(28.45788446, 77.2877589);
marker_pos[0] = new L.LatLng(28.4588446, 77.2867589);
marker_pos[1] = new L.LatLng(28.4578446, 77.2867589);
marker_pos[2] = new L.LatLng(28.45788446, 77.2877589);
var locationIcon = L.icon({
iconUrl: 'location.png',
iconSize: [32, 32],
iconAnchor: [16, 16]
// popupAnchor: [-3, -76],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
var tractorIcon = L.icon({
iconUrl: 'tractor.png',
iconSize: [32, 50],
iconAnchor: [16, 25]
// popupAnchor: [-3, -76],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
//var marker_a = new L.Marker(a, { icon: tractorIcon, draggable: true }).addTo(map);
//marker_b = new L.Marker(b, { icon: locationIcon, draggable: true }).addTo(map);
//marker_c = new L.Marker(c, { icon: locationIcon, draggable: true }).addTo(map);
marker_arr[0] = new L.Marker(marker_pos[0], { icon: tractorIcon, draggable: true }).addTo(map);
marker_arr[1] = new L.Marker(marker_pos[1], { icon: locationIcon, draggable: true }).addTo(map);
marker_arr[2] = new L.Marker(marker_pos[2], { icon: locationIcon, draggable: true }).addTo(map);
var polyline_demo = new L.Polyline([marker_pos[0], marker_pos[1], marker_pos[2]]).addTo(map); // make the polyline as well
var myGroup = L.layerGroup([marker_arr[0], marker_arr[1], marker_arr[2]]);
myGroup.eachLayer(function (layer) {
layer.setOpacity(0.5);
});
//L.marker([50.505, 30.57], { icon: myIcon }).addTo(map);
//marker = L.marker([28.4598446,77.2867589], { icon: tractorIcon, draggable: true }).addTo(map).on('click', onTractor);
// Now on dragstart you'll need to find the latlng from the polyline which corresponds
// with your marker's latlng and store it's key in your marker instance so you can use it later on:
function dragStartHandler(e) {
var latlngPoly = polyline_demo.getLatLngs(), // Get the polyline's latlngs
//var latlngPoly = polyline3.getLatLngs() // *** NOT WORKING !
latlngMarker = this.getLatLng(); // Get the actual, cliked MARKER's start latlng
console.log("start");
for (var i = 0; i < latlngPoly.length; i++) { // Iterate the polyline's latlngs
if (latlngMarker.equals(latlngPoly[i])) { // Compare marker's latlng ot the each polylines
this.polylineLatlng = i; // If equals store key in marker instance
}
}
}
// Now you know the key of the polyline's latlng you can change it
// when dragging the marker on the dragevent:
function dragHandler(e) {
var latlngPoly = polyline_demo.getLatLngs(), // Get the polyline's latlngs
//var latlngPoly = polyline3.getLatLngs() // *** NOT WORKING !
latlngMarker = this.getLatLng(); // Get the marker's current latlng
console.log("drag");
latlngPoly.splice(this.polylineLatlng, 1, latlngMarker); // Replace the old latlng with the new
polyline_demo.setLatLngs(latlngPoly); // Update the polyline with the new latlngs
//polyline3.setLatLngs(latlngPoly); // *** NOT WORKING !
}
// Just to be clean and tidy remove the stored key on dragend:
function dragEndHandler(e) {
delete this.polylineLatlng;
console.log("end");
}
//You'll need to attach eventlisteners and callbacks to your L.Marker's.
// You could automate this, but i'll keep it simple for now:
//
marker_arr[0]
.on('dragstart', dragStartHandler)
.on('drag', dragHandler)
.on('dragend', dragEndHandler);
marker_arr[1]
.on('dragstart', dragStartHandler)
.on('drag', dragHandler)
.on('dragend', dragEndHandler);
marker_arr[2]
.on('dragstart', dragStartHandler)
.on('drag', dragHandler)
.on('dragend', dragEndHandler);
///////////////////////////////////////////////////////////////////////////////
var doRouting = false;
var startPoint = [28.4588446, 77.2867589];
var arr = []; //Arreay for routing lines
var lineCount = 0;
// make a new 2D polyline array
var newPoly = new Array(20);
// Loop to create 2D array using 1D array
for (var i = 0; i < newPoly.length; i++) {
newPoly[i] = new Array(2);
}
function btnRouting() {
var property = document.getElementById("myRouting");
if (doRouting) {
doRouting = false;
property.style.backgroundColor = "#ecebeb"
console.log('Line count: ');
console.log(lineCount);
//make one polyline from clickings, which shall me draggable later
//var polyline2 = new L.Polyline(pp, { color: 'red' }).addTo(map);
var newPoly2 = new Array(lineCount + 1); // this is required, becuse newPoly have empty values, which is not accepted by L.Polyline
// Loop to create 2D array using 1D array
for (var i = 0; i < newPoly2.length; i++) {
newPoly2[i] = new Array(2);
newPoly2[i][0] = newPoly[i][0];
newPoly2[i][1] = newPoly[i][1];
}
console.log(newPoly);
console.log(newPoly2);
console.log('orange');
//make one polyline from clickings, which shall be draggable later:
// ****** THIS IS NOT MOVING IF I CHANGE it in the HANDLERS *******//
var polyline3 = new L.Polyline(newPoly2, { color: '#00AA00', weight: 10, opacity: 0.4 }).addTo(map);
//*****************************************************************//
} else { //End the routing
doRouting = true;
property.style.backgroundColor = "#7FFF00"
}
}
map.on("click", function (e) { //Listener: Click on MAP -> Addign the WAYPOINTS
if (doRouting) {
var newLine = [
startPoint,
[e.latlng.lat, e.latlng.lng] //mouse click position in lat & long
];
//arr[lineCount][0] = startPoint[0];
//arr[lineCount][1] = startPoint[1];
//arr[lineCount][2] = e.latlng.lat;
//arr[lineCount][3] = e.latlng.lng;
newPoly[lineCount][0] = startPoint[0];
newPoly[lineCount][1] = startPoint[1];
newPoly[lineCount + 1][0] = e.latlng.lat;
newPoly[lineCount + 1][1] = e.latlng.lng;
lineCount++;
// initial line & marker:
new L.polyline(newLine, { color: 'blue', noClip: true }).addTo(map);
//L.circleMarker([e.latlng.lat, e.latlng.lng]).addTo(map); //move the Waypoint
marker_new[lineCount] = new L.marker([e.latlng.lat, e.latlng.lng], { icon: locationIcon, draggable: true, opacity: 0.4 }).addTo(map).on('dragstart', dragStartHandler).on('drag', dragHandler).on('dragend', dragEndHandler);
startPoint = [e.latlng.lat, e.latlng.lng];
console.log(arr);
}
else {
// console.log(L.circleMarker.getLatLng()[0]); //detect which waypoint is selected
}
})
我更新了你的代码:https://jsfiddle.net/falkedesign/h5cyk1up/
我改变了什么:
- 我在标记中添加了 parentLine
marker_arr[0].parentLine = polyline_demo;
和 marker_new[lineCount].parentLine = tempLine;
- 读出 handlers 中的 parentLine:
var polyline = e.target.parentLine;
if(polyline){
var latlngPoly = polyline.getLatLngs(),
- 在点击处理程序中(添加标记):
将 latlng 添加到 tempLine 或创建一个新的
if(!tempLine){
tempLine = L.polyline([], { color: 'blue', noClip: true }).addTo(map);
}
tempLine.addLatLng(e.latlng);
- 完成路由后,更改折线的样式并将tempLine设置为空以生成新路由:
var polyline = tempLine.setStyle({ color: '#00AA00', weight: 10, opacity: 0.4 });
tempLine = null;
问题:通过在地图上单击并沿着多段线拖动来放置标记,就像丝带一样不起作用。
我有一个类似的项目:
不幸的是,新的(绿色)线没有用标记(像丝带)拉出来。 那么,程序是如何工作的:
- 使用“路由”按钮生成一些 HTML。 - 工作。
- 使用以下代码生成带有初始线(红色)和标记的地图:- 工作。
- 点击“路线”按钮可以通过点击地图在地图上做标记。 - 工作。
- 用蓝线连接标记。 - 工作。
- 再次点击“Rouring”按钮找到路线 - Working。
- 将线条转换为一条绿色折线(稍后必须将此线与新标记一起拖动。)- 工作。
- 所以当我拖动标记时,只有标记在移动,线没有,但是我分配了三个安德勒。
为了更容易找到问题,在 script.js:
中搜索“*”index.html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin="" />
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin=""></script>
<style>
#fieldMap {
height: 600px;
}
</style>
<title> DRAG Polyline</title>
</head>
<body>
<table style="width:100%">
<tr>
<td>Latitude: <span id="lat"></span></td>
<td>Longitude: <span id="lon"></span></td>
</tr>
<tr>
<td> <span id="client"></span></td>
<td><span id="screen"></span></td>
</tr>
<tr>
<td> <button id="myRouting" onclick="btnRouting()">Routing</button></td>
<td><button id="myRoutSave" onclick="myRoutSave()">Save Route</button></td>
</tr>
<tr>
<td> <button id="myRoutLoad" onclick="myRoutLoad()">Load Route</button></td>
<td><button id="myRoutSend" onclick="myRoutSend()">Send Route</button></td>
</tr>
</table>
<div id="fieldMap"></div>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
script.js:
const map = L.map('fieldMap').setView([28.4588446, 77.2867589], 17); //The initial point
var layer = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
map.addLayer(layer); // Adding layer to the map
var marker_arr = [];
var marker_pos = [];
var marker_new = [];
///////////////////
// ADD markers :
//var a = new L.LatLng(28.4588446, 77.2867589),
// b = new L.LatLng(28.4578446, 77.2867589),
// c = new L.LatLng(28.45788446, 77.2877589);
marker_pos[0] = new L.LatLng(28.4588446, 77.2867589);
marker_pos[1] = new L.LatLng(28.4578446, 77.2867589);
marker_pos[2] = new L.LatLng(28.45788446, 77.2877589);
var locationIcon = L.icon({
iconUrl: 'location.png',
iconSize: [32, 32],
iconAnchor: [16, 16]
// popupAnchor: [-3, -76],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
var tractorIcon = L.icon({
iconUrl: 'tractor.png',
iconSize: [32, 50],
iconAnchor: [16, 25]
// popupAnchor: [-3, -76],
// shadowUrl: 'my-icon-shadow.png',
// shadowSize: [68, 95],
// shadowAnchor: [22, 94]
});
//var marker_a = new L.Marker(a, { icon: tractorIcon, draggable: true }).addTo(map);
//marker_b = new L.Marker(b, { icon: locationIcon, draggable: true }).addTo(map);
//marker_c = new L.Marker(c, { icon: locationIcon, draggable: true }).addTo(map);
marker_arr[0] = new L.Marker(marker_pos[0], { icon: tractorIcon, draggable: true }).addTo(map);
marker_arr[1] = new L.Marker(marker_pos[1], { icon: locationIcon, draggable: true }).addTo(map);
marker_arr[2] = new L.Marker(marker_pos[2], { icon: locationIcon, draggable: true }).addTo(map);
var polyline_demo = new L.Polyline([marker_pos[0], marker_pos[1], marker_pos[2]]).addTo(map); // make the polyline as well
var myGroup = L.layerGroup([marker_arr[0], marker_arr[1], marker_arr[2]]);
myGroup.eachLayer(function (layer) {
layer.setOpacity(0.5);
});
//L.marker([50.505, 30.57], { icon: myIcon }).addTo(map);
//marker = L.marker([28.4598446,77.2867589], { icon: tractorIcon, draggable: true }).addTo(map).on('click', onTractor);
// Now on dragstart you'll need to find the latlng from the polyline which corresponds
// with your marker's latlng and store it's key in your marker instance so you can use it later on:
function dragStartHandler(e) {
var latlngPoly = polyline_demo.getLatLngs(), // Get the polyline's latlngs
//var latlngPoly = polyline3.getLatLngs() // *** NOT WORKING !
latlngMarker = this.getLatLng(); // Get the actual, cliked MARKER's start latlng
console.log("start");
for (var i = 0; i < latlngPoly.length; i++) { // Iterate the polyline's latlngs
if (latlngMarker.equals(latlngPoly[i])) { // Compare marker's latlng ot the each polylines
this.polylineLatlng = i; // If equals store key in marker instance
}
}
}
// Now you know the key of the polyline's latlng you can change it
// when dragging the marker on the dragevent:
function dragHandler(e) {
var latlngPoly = polyline_demo.getLatLngs(), // Get the polyline's latlngs
//var latlngPoly = polyline3.getLatLngs() // *** NOT WORKING !
latlngMarker = this.getLatLng(); // Get the marker's current latlng
console.log("drag");
latlngPoly.splice(this.polylineLatlng, 1, latlngMarker); // Replace the old latlng with the new
polyline_demo.setLatLngs(latlngPoly); // Update the polyline with the new latlngs
//polyline3.setLatLngs(latlngPoly); // *** NOT WORKING !
}
// Just to be clean and tidy remove the stored key on dragend:
function dragEndHandler(e) {
delete this.polylineLatlng;
console.log("end");
}
//You'll need to attach eventlisteners and callbacks to your L.Marker's.
// You could automate this, but i'll keep it simple for now:
//
marker_arr[0]
.on('dragstart', dragStartHandler)
.on('drag', dragHandler)
.on('dragend', dragEndHandler);
marker_arr[1]
.on('dragstart', dragStartHandler)
.on('drag', dragHandler)
.on('dragend', dragEndHandler);
marker_arr[2]
.on('dragstart', dragStartHandler)
.on('drag', dragHandler)
.on('dragend', dragEndHandler);
///////////////////////////////////////////////////////////////////////////////
var doRouting = false;
var startPoint = [28.4588446, 77.2867589];
var arr = []; //Arreay for routing lines
var lineCount = 0;
// make a new 2D polyline array
var newPoly = new Array(20);
// Loop to create 2D array using 1D array
for (var i = 0; i < newPoly.length; i++) {
newPoly[i] = new Array(2);
}
function btnRouting() {
var property = document.getElementById("myRouting");
if (doRouting) {
doRouting = false;
property.style.backgroundColor = "#ecebeb"
console.log('Line count: ');
console.log(lineCount);
//make one polyline from clickings, which shall me draggable later
//var polyline2 = new L.Polyline(pp, { color: 'red' }).addTo(map);
var newPoly2 = new Array(lineCount + 1); // this is required, becuse newPoly have empty values, which is not accepted by L.Polyline
// Loop to create 2D array using 1D array
for (var i = 0; i < newPoly2.length; i++) {
newPoly2[i] = new Array(2);
newPoly2[i][0] = newPoly[i][0];
newPoly2[i][1] = newPoly[i][1];
}
console.log(newPoly);
console.log(newPoly2);
console.log('orange');
//make one polyline from clickings, which shall be draggable later:
// ****** THIS IS NOT MOVING IF I CHANGE it in the HANDLERS *******//
var polyline3 = new L.Polyline(newPoly2, { color: '#00AA00', weight: 10, opacity: 0.4 }).addTo(map);
//*****************************************************************//
} else { //End the routing
doRouting = true;
property.style.backgroundColor = "#7FFF00"
}
}
map.on("click", function (e) { //Listener: Click on MAP -> Addign the WAYPOINTS
if (doRouting) {
var newLine = [
startPoint,
[e.latlng.lat, e.latlng.lng] //mouse click position in lat & long
];
//arr[lineCount][0] = startPoint[0];
//arr[lineCount][1] = startPoint[1];
//arr[lineCount][2] = e.latlng.lat;
//arr[lineCount][3] = e.latlng.lng;
newPoly[lineCount][0] = startPoint[0];
newPoly[lineCount][1] = startPoint[1];
newPoly[lineCount + 1][0] = e.latlng.lat;
newPoly[lineCount + 1][1] = e.latlng.lng;
lineCount++;
// initial line & marker:
new L.polyline(newLine, { color: 'blue', noClip: true }).addTo(map);
//L.circleMarker([e.latlng.lat, e.latlng.lng]).addTo(map); //move the Waypoint
marker_new[lineCount] = new L.marker([e.latlng.lat, e.latlng.lng], { icon: locationIcon, draggable: true, opacity: 0.4 }).addTo(map).on('dragstart', dragStartHandler).on('drag', dragHandler).on('dragend', dragEndHandler);
startPoint = [e.latlng.lat, e.latlng.lng];
console.log(arr);
}
else {
// console.log(L.circleMarker.getLatLng()[0]); //detect which waypoint is selected
}
})
我更新了你的代码:https://jsfiddle.net/falkedesign/h5cyk1up/
我改变了什么:
- 我在标记中添加了 parentLine
marker_arr[0].parentLine = polyline_demo;
和marker_new[lineCount].parentLine = tempLine;
- 读出 handlers 中的 parentLine:
var polyline = e.target.parentLine;
if(polyline){
var latlngPoly = polyline.getLatLngs(),
- 在点击处理程序中(添加标记):
将 latlng 添加到 tempLine 或创建一个新的
if(!tempLine){
tempLine = L.polyline([], { color: 'blue', noClip: true }).addTo(map);
}
tempLine.addLatLng(e.latlng);
- 完成路由后,更改折线的样式并将tempLine设置为空以生成新路由:
var polyline = tempLine.setStyle({ color: '#00AA00', weight: 10, opacity: 0.4 });
tempLine = null;