Leaflet v1.03: 如何使圆形标记可拖动?

3

有没有一些了解Leaflet的专家知道,在Leaflet v1.0.3中使一个CircleMarker可拖动的最简单方法是什么?

对于“标准”标记,使用“draggable”选项很容易实现。但是CircleMarker没有这样的选项。我尝试使用多个事件来解决问题,但问题在于移动的不是标记,而是底层地图。

另一种可能性是使用“stopPropagation”函数(但仅适用于DOM事件)。或者使用“removeEventParent”... 如果CircleMarker的“parent”是地图及其事件呢?根据文档,还有DOMUtility/Draggable类。这是我需要的吗?

<!DOCTYPE html>
<html>
 <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Draggable Markers</title>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css" />
  <script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
        <style>
            body {padding: 0; margin: 0;}
            html, body, #map {height: 100%;}
      </style>
 </head>
 
 <body>
  <div id="map"></div>
  <script>
            var layerOsm = new L.TileLayer('https://{s}.api.mapbox.com/v4/mapbox.outdoors/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoicHBldGUiLCJhIjoiY2lsdmE2ZmQ2MDA4OHZxbTZpcmx1emtqbSJ9.Two7SPSaIZysqgOTrrLkRg', {
           subdomains: 'ab', maxZoom: 20, noWrap:true, attribution:'<a href="http://www.mapbox.com">Mapbox</a> | <a href="http://www.openstreetmap.org/copyright/">OpenStreetMap</a>' });
   var map = new L.Map('map').addLayer(layerOsm).setView(new L.LatLng(47.8, 13.0), 14);
            L.marker([47.8, 13.0], {draggable:true}).addTo(map);
            
            var circle = L.circleMarker([47.81, 13.01], {radius:30}).addTo(map);

            circle.on('mousedown', function () {
                map.on('mousemove', function (e) {
                    circle.setLatLng(e.latlng);
                });
            }); 
            map.on('mouseup', function(){
                map.removeEventListener('mousemove');
            })
  </script>
 </body>
</html>


1
我刚刚谷歌了一下,因为我也在尝试使圆形标记可拖动。我以为这对于一个星期五的下午来说是一件容易的事情,但并非如此。 - Bill Chappell
不使用 L.circleMarker,但可以替换为 L.divIcon() 并使用 CSS 使其看起来像一个圆形,这样就可以将其设置为可拖动。请参见 https://gis.stackexchange.com/a/226814/。 - user2441511
可能是重复的问题:如何使leaflet圆形标记可拖动?(链接:https://dev59.com/7YXca4cB1Zd3GeqPHmST) - Xpleria
2个回答

12

Leaflet v1.0+ 解决方案:

var marker = L.circleMarker([41.91847, -74.62634]).addTo(map)

// extract trackCursor as a function so this specific
// "mousemove" listener can be removed on "mouseup" versus
// all listeners if we were to use map.off("mousemove")
function trackCursor(evt) {
  marker.setLatLng(evt.latlng)
}
    
marker.on("mousedown", function() {
  map.dragging.disable()
  map.on("mousemove", trackCursor)
})

map.on("mouseup", function() {
  map.dragging.enable()
  map.off("mousemove", trackCursor)
})

为了使这种行为更具可重用性,我们可以将其封装在一个函数中(JS ES6 语法):

function moveableMarker(map, marker) {
  function trackCursor(evt) {
    marker.setLatLng(evt.latlng)
  }

  marker.on("mousedown", () => {
    map.dragging.disable()
    map.on("mousemove", trackCursor)
  })

  marker.on("mouseup", () => {
    map.dragging.enable()
    map.off("mousemove", trackCursor)
  })

  return marker
}

你可以通过以下方式使标记可拖动/移动:

const moveable = moveableMarker(map, marker)

这些示例有助于构建上述解决方案:


谢谢Bill,你在codepen.io上的例子可行,但jsfiddle上的另一个例子只适用于Leaflet 0.7版本,而不是v1.0.3(地图被移动而不是圆形)。仍然很复杂,需要处理多个事件并切换map.dragging开/关来移动circleMarker。 - SammyC
谢谢Bill。非常好的解决方案。可以将此解决方案适应于Circle的子类或具有LatLng的任何其他对象的功能。我现在使用它来移动CircleMarker。 - Dawied
这很棒,但如果您在悬停在另一个标记上时发生鼠标抬起事件,则该事件不会触发。将处理程序注册到地图而不是标记上会更好。例如:map.on("mouseup", ... - bendytree

1

https://github.com/w8r/Leaflet.Path.Drag/上找到了另一个答案。我刚刚添加了Leaflet.Path.Drag.js。现在我可以从我的REST服务中读取所有站点并移动它们。

var data = {
    "type": "FeatureCollection",
    "features": [
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -73.7979125, 42.704642
                ]
            },
            "type": "Feature",
            "properties": {
                "popupContent": "This is Point 1. "
            },
            "id": 51
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -73.630371,42.698585
                ]
            },
            "type": "Feature",
            "properties": {
                "popupContent": "This is Point 2. "
            },
            "id": 52
        }
    ]
};

var map = L.map('map', {editable: true}).setView([43, -74], 8);

var osm=new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',{ 
                attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> //contributors'}).addTo(map);


function onEachFeature(feature, layer) {
var popupContent = feature.properties.popupContent
layer.bindPopup(popupContent);

    layer.on('dragend', function(e){
        console.log(layer.getLatLng().lat);
        console.log(layer.getLatLng().lng);
    });

}

var mymarker =L.geoJSON(data, {

style: function (feature) {
    return feature.properties && feature.properties.style;
},

onEachFeature: onEachFeature,

pointToLayer: function (feature, latlng) {
    return L.circleMarker(latlng,{ draggable: true }, {
        radius: 8,
        fillColor: "#ff7800",
        color: "#000",
        weight: 1,
        opacity: 1,
        fillOpacity: 0.8
    });
}
}).addTo(map);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接