如何使用 Leaflet 检测多边形边缘上的点击?
How can I detect a click on the edge of a polygon with Leaflet?
情况:
我有一张传单地图(Leaflet.draw)。这张地图上有各种几何图形(点、线、多边形),添加为 geoJson(使用 L.geoJson)。每个几何图形都有一个点击处理程序。
问题:
当有人在多边形内部单击时,将触发单击事件。
解决方案:
我只希望在单击多边形边(闭合折线)时触发单击事件。解决方法是检测点击到边缘的距离。
我找不到针对此问题的记录解决方案。将不胜感激。
我能想到的一种方法是创建一条具有相同坐标的附加折线并将其放在多边形的顶部,并使多边形不可点击。这将需要使用 onEachFeature
.
添加一些逻辑来创建 GeoJSON 特征
Leaflet 的多边形(和折线)由单个 SVG 元素组成,我不确定是否可以在不进行一些 Javascript 数学运算或类似操作的情况下检测外边缘上的点击,onclick
事件只是附加到整个元素。
var polyoverlay = new L.featureGroup().addTo(map);
var edgeoverlay = new L.featureGroup().addTo(map);
var geojsonobj = {"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {}, "geometry": {"type": "Polygon", "coordinates": [[[-87.027648, 20.820875 ], [-87.027648, 21.320875 ], [-86.527648, 21.320875 ], [-86.527648, 20.820875 ], [-87.027648, 20.820875 ] ] ] } } ] };
var poly = L.geoJson(geojsonobj, {
onEachFeature: function(feature, layer){
// latitude/longitude to longitude/latitude coordinates
var lonlats = [];
feature.geometry.coordinates[0].forEach(function(f){
lonlats.push([f[1], f[0]]);
});
// add polyline to map
var polyline = L.polyline(lonlats,{
color: 'black'
}).bindPopup('hello').addTo(edgeoverlay);
// add polygon to map
var polygon = L.polygon(lonlats,{
color: 'blue',
clickable: false
}).addTo(polyoverlay);
}
});
在忽略@chrki 的答案的同时开始这个答案,我的很相似但结果有点不同,使用更少的逻辑和更少的层。所以我想我会把它扔在这里以备不时之需。
如前所述,Leaflet 无法检测边缘点击。将事件附加到功能后,它会响应整个元素。您可以做的是双重绘制要素,将多段线放在 geojson 层生成的多边形的顶部,并将侦听器附加到多段线而不是多边形。
// Create geojson layer w/o adding data
var geojson = new L.GeoJSON(null, {
// Don't draw the stroke
style: function () {
return {
stroke: false
}
},
onEachFeature: function (feature, layer) {
// Check if layer is a polygon
if (layer instanceof L.Polygon) {
// Fetch coordinates from polygon
var latLngs = layer.getLatLngs();
// Push first coordinate to complete line
latLngs.push(latLngs[0]);
// Create polyline using coordinates
var polyline = new L.Polyline(latLngs);
// Add click listener
polyline.on('click', function () {
alert('Polyline clicked!');
});
// Add polyline to featuregroup
polyline.addTo(featureGroup);
}
}
}).addTo(map);
// Create featuregroup, add it to the map
var featureGroup = new L.FeatureGroup().addTo(map);
// Test
geojson.addData({
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-45, -45],
[-45, 45],
[45, 45],
[45, -45],
[-45, -45]
]]
}
}]
});
Plunker 上的工作示例:http://plnkr.co/edit/d1tLOIEeBPsv7YFDWavA?p=preview
情况: 我有一张传单地图(Leaflet.draw)。这张地图上有各种几何图形(点、线、多边形),添加为 geoJson(使用 L.geoJson)。每个几何图形都有一个点击处理程序。
问题: 当有人在多边形内部单击时,将触发单击事件。
解决方案: 我只希望在单击多边形边(闭合折线)时触发单击事件。解决方法是检测点击到边缘的距离。
我找不到针对此问题的记录解决方案。将不胜感激。
我能想到的一种方法是创建一条具有相同坐标的附加折线并将其放在多边形的顶部,并使多边形不可点击。这将需要使用 onEachFeature
.
Leaflet 的多边形(和折线)由单个 SVG 元素组成,我不确定是否可以在不进行一些 Javascript 数学运算或类似操作的情况下检测外边缘上的点击,onclick
事件只是附加到整个元素。
var polyoverlay = new L.featureGroup().addTo(map);
var edgeoverlay = new L.featureGroup().addTo(map);
var geojsonobj = {"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {}, "geometry": {"type": "Polygon", "coordinates": [[[-87.027648, 20.820875 ], [-87.027648, 21.320875 ], [-86.527648, 21.320875 ], [-86.527648, 20.820875 ], [-87.027648, 20.820875 ] ] ] } } ] };
var poly = L.geoJson(geojsonobj, {
onEachFeature: function(feature, layer){
// latitude/longitude to longitude/latitude coordinates
var lonlats = [];
feature.geometry.coordinates[0].forEach(function(f){
lonlats.push([f[1], f[0]]);
});
// add polyline to map
var polyline = L.polyline(lonlats,{
color: 'black'
}).bindPopup('hello').addTo(edgeoverlay);
// add polygon to map
var polygon = L.polygon(lonlats,{
color: 'blue',
clickable: false
}).addTo(polyoverlay);
}
});
在忽略@chrki 的答案的同时开始这个答案,我的很相似但结果有点不同,使用更少的逻辑和更少的层。所以我想我会把它扔在这里以备不时之需。
如前所述,Leaflet 无法检测边缘点击。将事件附加到功能后,它会响应整个元素。您可以做的是双重绘制要素,将多段线放在 geojson 层生成的多边形的顶部,并将侦听器附加到多段线而不是多边形。
// Create geojson layer w/o adding data
var geojson = new L.GeoJSON(null, {
// Don't draw the stroke
style: function () {
return {
stroke: false
}
},
onEachFeature: function (feature, layer) {
// Check if layer is a polygon
if (layer instanceof L.Polygon) {
// Fetch coordinates from polygon
var latLngs = layer.getLatLngs();
// Push first coordinate to complete line
latLngs.push(latLngs[0]);
// Create polyline using coordinates
var polyline = new L.Polyline(latLngs);
// Add click listener
polyline.on('click', function () {
alert('Polyline clicked!');
});
// Add polyline to featuregroup
polyline.addTo(featureGroup);
}
}
}).addTo(map);
// Create featuregroup, add it to the map
var featureGroup = new L.FeatureGroup().addTo(map);
// Test
geojson.addData({
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-45, -45],
[-45, 45],
[45, 45],
[45, -45],
[-45, -45]
]]
}
}]
});
Plunker 上的工作示例:http://plnkr.co/edit/d1tLOIEeBPsv7YFDWavA?p=preview