【问题标题】:Python - jinja2 template picks up only the first record from the dataPython - jinja2 模板只从数据中提取第一条记录
【发布时间】:2023-01-20 20:01:47
【问题描述】:

我想在点击标记时出现一个圆圈的点击功能。 到目前为止,我已经开发了包含相关元素的类,如下面的代码所示:

df = pd.read_csv("survey.csv")

class Circle(MacroElement):

def __init__(self):
    for i,row in df.iterrows():
        rad = int(df.at[i, 'radius'])

def __init__(self,
             popup=None
             ):
    super(Circle, self).__init__()
    self._name = 'Circle',
    self.radius = rad * 1560
    
    self._template = Template(u"""
        {% macro script(this, kwargs) %}
            var circle_job = L.circle();
            function newCircle(e){
                circle_job.setLatLng(e.latlng).addTo({{this._parent.get_name()}});
                circle_job.setRadius({{this.radius}});
                circle_job.setStyle({
                color: 'black',
                fillcolor: 'black'
                });
                };
            {{this._parent.get_name()}}.on('click', newCircle);      
        {% endmacro %}
        """)  # noqa
    



for i,row in df.iterrows():
lat =df.at[i, 'lat']
lng = df.at[i, 'lng']
sp = df.at[i, 'sp']
phone = df.at[i, 'phone']
role = df.at[i, 'role']
rad = int(df.at[i, 'radius'])


popup = '<b>Phone: </b>' + str(df.at[i,'phone'])
job_range = Circle()

if role == 'Contractor':
    fs.add_child(
        folium.Marker(location=[lat,lng],
                  tooltip=folium.map.Tooltip(
                      text='<strong>Contact surveyor</strong>',
                      style=("background-color: lightgreen;")),
                  popup=popup,
                  icon = folium.Icon(color='darkred', icon='glyphicon-user'
                                     )
                )
    )
    fs.add_child (
        folium.Marker(location=[lat,lng],
                  popup=popup,
                  icon = folium.DivIcon(html="<b>" + sp + "</b>",
                                        class_name="mapText_contractor",
                                        icon_anchor=(30,5))
                  #click_action = js_f
                )
    )
    fs.add_child(job_range)

这有效但不幸的是只考虑了第一个记录。

我怎样才能使这些弹出圆圈调整到给定输入的半径(如 CSV 文档中所示?)?

【问题讨论】:

  • 如果最终目标是在地图上绘制标记,然后在弹出窗口打开或单击事件上绘制圆圈,我建议您修改folium.Marker 模板以在此类单击事件中包含 javascript sn-p。然后,javascript 代码将包含一个在弹出窗口打开时绘制圆圈的函数。
  • 我不知道该怎么做。我尝试使用 click_action 属性,但它根本不起作用。
  • 请参阅提供的答案。

标签: python pandas jinja2 folium


【解决方案1】:

您可以更改标记模板以包含点击功能。单击函数将打开弹出窗口并绘制一个圆圈。请参见下面的示例。

import pandas as pd
import numpy as np
import folium
from folium.map import Template, Marker

start_coords = (52.4972664,-2.0037126)
m = folium.Map(start_coords)


def generate_data(start_coords, n):
    roles = {0: 'Full', 1: 'Contractor'}
    df = pd.DataFrame()
    df['lat'] = [start_coords[0]+i for i in np.random.uniform(-1, 1, n)]
    df['lon'] = [start_coords[1]+i for i in np.random.uniform(-1, 1, n)]
    df['phone'] = [''.join(map(str, i)) for i in np.random.randint(1, 10, (n, 11))]
    df['radius'] = [10*i for i in np.random.randint(1, 9, n)]
    df['role'] = [roles[i] for i in np.random.randint(0, 2, n)]
    
    return df


# Modify Marker template to include the onClick event
click_template = """{% macro script(this, kwargs) %}
    var {{ this.get_name() }} = L.marker(
        {{ this.location|tojson }},
        {{ this.options|tojson }}
    ).addTo({{ this._parent.get_name() }}).on('click', addCircle).on('popupclose', removeCircle);
{% endmacro %}"""

# Change template to custom template
Marker._template = Template(click_template)

map_id = m.get_name()
#Add javascript snippet to draw cricles
click_js = f"""function removeCircle() {{
                 {map_id}.eachLayer(function(layer){{
                   if (layer instanceof L.Circle)
                      {{ {map_id}.removeLayer(layer) }}
                      }});
                }}


               function addCircle(e) {{                
                 coords = e.latlng                                 
                 var radius = e.target.options.radius * 1560; 
                 var color = e.target.options.circleColor;               
                 removeCircle() //remove existing circles                
                      
                 var circle = L.circle([coords.lat,coords.lng], {{radius: radius}}).addTo({map_id}) 
                 circle.setStyle({{
                    color: color,
                    fillcolor: color
                }});
                 }}"""
                 

e = folium.Element(click_js)
html = m.get_root()
html.script.add_child(e)

n = 10 # number of markers
df = generate_data(start_coords, n)

for i, row in df.iterrows():
    popup = f'<b>Phone: {row["phone"]}</b>' 
    icon_color = 'darkred' if row['role'] == 'Contractor' else 'black'
    folium.Marker([row['lat'], row['lon']],
                  popup=popup,
                  icon = folium.Icon(color=icon_color, icon='glyphicon-user'),
                  radius=row['radius'],
                  circleColor=icon_color
                 ).add_to(m)
    
m.fit_bounds(m.get_bounds())
m

【讨论】:

  • 我想我们很接近。我刚收到 Typeerror,即:Map 对象不可调用。
  • 你知道哪一行给你 TypeError 吗?
  • 是的,正是:df = generate_data(start_coords, n)
  • 除非您修改上面提供的示例,否则我在该 generate_data 函数中看不到名为 Map 的变量。
  • 我刚刚根据我的工作文件将 m 更改为 map
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
相关资源
最近更新 更多