如何通过点击复制 folium 地图上的标记位置?

2024-05-16


I am able to print the location of a given marker on the map using folium.plugins.MousePosition.
class GeoMap:
        
    def update(self, location_center:np.array, locations: np.array):
        self.map = folium.Map(location_center, zoom_start=10)
        for i in range(locations.shape[0]):
            location = tuple(locations[i, j] for j in range(locations.shape[1]))
            folium.Marker(
                location=location,
            ).add_to(self.map)
        formatter = "function(num) {return L.Util.formatNum(num, 3) + ' º ';};"
        plugins.MousePosition(
            position="topright",
            separator=" | ",
            empty_string="NaN",
            lng_first=True,
            num_digits=20,
            prefix="Coordinates:",
            lat_formatter=formatter,
            lng_formatter=formatter,
        ).add_to(self.map)
        
    def display(self):
        display(self.map)

但是,我希望用户能够通过单击来复制 folium 地图上的标记位置。我想可能有一种方法可以使用 on_click 事件(在 Python 中)获取标记的位置。但是,我在网上没有找到任何示例。

我正在使用 Python,但如果您有一个使用 Python 和一些 Javascript 运行良好的解决方案,那也可以。

任何帮助将非常感激 !

Thanks,


使用按钮复制

由于您正在使用标记,因此您可以添加popup https://python-visualization.github.io/folium/modules.html#folium.map.Marker到每个标记。单击标记图标时将打开弹出窗口。popup可以采取html字符串作为输入,因此您可以使用它来插入复制按钮或类似的内容。

随后,您需要添加一个javascript将函数复制到foliumhtml 输出。这可以通过以下方式完成MacroElement https://stackoverflow.com/a/58802382/11380795.

实施this https://www.w3schools.com/howto/howto_js_copy_clipboard.asp将产生以下基本示例:

import folium
import jinja2

location_center = [45.5236, -122.6750]
locations = [[45.5012, -122.6655],[45.5132, -122.6708],[45.5275, -122.6692],[45.5318, -122.6745]]

m = folium.Map(location_center, zoom_start=13)
for location in locations:
    folium.Marker(
        location=location,
        popup = f'<input type="text" value="{location[0]}, {location[1]}" id="myInput"><button onclick="myFunction()">Copy location</button>'
    ).add_to(m)
    
el = folium.MacroElement().add_to(m)
el._template = jinja2.Template("""
    {% macro script(this, kwargs) %}
    function myFunction() {
      /* Get the text field */
      var copyText = document.getElementById("myInput");

      /* Select the text field */
      copyText.select();
      copyText.setSelectionRange(0, 99999); /* For mobile devices */

      /* Copy the text inside the text field */
      document.execCommand("copy");
    }
    {% endmacro %}
""")

display(m)

点击事件复制

如果您希望在单击标记时直接复制纬度和经度:这也是可能的,但需要猴子修补 https://github.com/python-visualization/folium/issues/494#issuecomment-272726740 the Marker's jinja template https://github.com/python-visualization/folium/blob/c25c84c888415a8f242e133c97242e26c3070fe6/folium/map.py#L264添加点击事件。需要猴子修补,因为标记的模板是硬编码的folium.

此外,单击时触发的功能可以定义为MacroElement:

import folium
import jinja2
from jinja2 import Template
from folium.map import Marker

tmpldata = """<!-- monkey patched Marker template -->
{% macro script(this, kwargs) %}
    var {{ this.get_name() }} = L.marker(
        {{ this.location|tojson }},
        {{ this.options|tojson }}
    ).addTo({{ this._parent.get_name() }}).on('click', onClick);
{% endmacro %}
"""

Marker._mytemplate = Template(tmpldata)
def myMarkerInit(self, *args, **kwargs):
    self.__init_orig__(*args, **kwargs)
    self._template = self._mytemplate
Marker.__init_orig__ = Marker.__init__
Marker.__init__ = myMarkerInit

location_center = [45.5236, -122.6750]
locations = [[45.5012, -122.6655],[45.5132, -122.6708],[45.5275, -122.6692],[45.5318, -122.6745]]

m = folium.Map(location_center, zoom_start=13)

for location in locations: #range(locations.shape[0]):
    folium.Marker(
        location=location,
        popup = f'<p id="latlon">{location[0]}, {location[1]}</p>'
    ).add_to(m)

el = folium.MacroElement().add_to(m)
el._template = jinja2.Template("""
    {% macro script(this, kwargs) %}
    function copy(text) {
        var input = document.createElement('textarea');
        input.innerHTML = text;
        document.body.appendChild(input);
        input.select();
        var result = document.execCommand('copy');
        document.body.removeChild(input);
        return result;
    };
    
    function getInnerText( sel ) {
        var txt = '';
        $( sel ).contents().each(function() {
            var children = $(this).children();
            txt += ' ' + this.nodeType === 3 ? this.nodeValue : children.length ? getInnerText( this ) : $(this).text();
        });
        return txt;
    };
    
    function onClick(e) {
       var popup = e.target.getPopup();
       var content = popup.getContent();
       text = getInnerText(content);
       copy(text);
    };
    {% endmacro %}
""")

display(m)

从可拖动标记复制

如果通过设置使用可拖动标记draggable=True在 Marker 对象中,从弹出窗口复制硬编码坐标是没有意义的。在这种情况下,您最好从 Marker 对象中检索最新坐标并相应地更新弹出窗口:

import folium
import jinja2
from jinja2 import Template
from folium.map import Marker

tmpldata = """<!-- monkey patched Marker template -->
{% macro script(this, kwargs) %}
    var {{ this.get_name() }} = L.marker(
        {{ this.location|tojson }},
        {{ this.options|tojson }}
    ).addTo({{ this._parent.get_name() }}).on('click', onClick);
{% endmacro %}
"""

Marker._mytemplate = Template(tmpldata)
def myMarkerInit(self, *args, **kwargs):
    self.__init_orig__(*args, **kwargs)
    self._template = self._mytemplate
Marker.__init_orig__ = Marker.__init__
Marker.__init__ = myMarkerInit

location_center = [45.5236, -122.6750]
locations = [[45.5012, -122.6655],[45.5132, -122.6708],[45.5275, -122.6692],[45.5318, -122.6745]]

m = folium.Map(location_center, zoom_start=13)

for location in locations: #range(locations.shape[0]):
    folium.Marker(
        location=location,
        popup = f'<p id="latlon">{location[0]}, {location[1]}</p>',
        draggable=True
    ).add_to(m)

el = folium.MacroElement().add_to(m)
el._template = jinja2.Template("""
    {% macro script(this, kwargs) %}
    function copy(text) {
        var input = document.createElement('textarea');
        input.innerHTML = text;
        document.body.appendChild(input);
        input.select();
        var result = document.execCommand('copy');
        document.body.removeChild(input);
        return result;
    };
    
    function onClick(e) {
       var lat = e.latlng.lat; 
       var lng = e.latlng.lng;
       var newContent = '<p id="latlon">' + lat + ', ' + lng + '</p>';
       e.target.setPopupContent(newContent);
       copy(lat + ', ' + lng);
    };
    {% endmacro %}
""")

display(m)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过点击复制 folium 地图上的标记位置? 的相关文章

随机推荐