javascript - 如何通过单击复制标记在folium Map 上的位置?

标签 javascript python folium

我可以使用 folium.plugins.MousePosition 在 map 上打印给定标记的位置。

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)
但是,我想让用户通过单击它来复制叶 map 上的标记位置。我想可能有一种方法可以使用 on_click 事件(在 Python 中)获取标记的位置。但是,我在网上没有找到任何示例。
我正在使用 Python,但如果您有一个使用 Python 和一些 Javascript 运行良好的解决方案,那也可以。
任何帮助将非常感激 !
谢谢,

最佳答案

用按钮复制
由于您正在使用标记,因此您可以添加 popup到每个标记。单击标记图标时将打开弹出窗口。 popup可以带html字符串作为输入,因此您可以使用它来插入复制按钮或类似的东西。
随后,您需要添加 javascript复制功能到folium html 输出。这可以通过 MacroElement 来完成.
实现 this将导致以下基本示例:

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)
enter image description here
复制点击事件
如果您希望在单击标记时直接复制纬度和经度:这也是可能的,但需要 monkey patching Markerjinja template添加点击事件。需要进行猴子修补,因为标记的模板在 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)

关于javascript - 如何通过单击复制标记在folium Map 上的位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67628175/

相关文章:

javascript - Vapor 3 接收包含 BOOL 的字符串化 JSON

python - 关于boost-python : dyld: Symbol not found: _PyBaseObject_Type

Python - 如何在方法内部捕获外部异常

python - 从Python中的folium map 中删除滚动条

javascript - 当到达 HTML 文件中的某个点时动画数字和文本

javascript - 从 Google App Engine 中的 .js 文件调用 JavaScript 函数

javascript - 如何在 JavaScript 中创建未初始化的对象?

python - 在 Python 中打开文件和 with 语句

python - 如何使用 GeoDataFrame 生成 Folium map ?

python - 尝试在 Django 服务器上渲染 Folium map 时出错