Skip to main content
 首页 » 编程设计

javascript之如何在 folium MarkerClusters 上显示平均值而不是计数

2024年11月24日35linjiqin

我在 python 中使用 folium 包来显示我的数据的 MarkerClusters。

当您没有完全放大时,集群看起来不错,但它们似乎显示该集群内子标记数量的计数。我理解为什么这是默认行为,但出于我的目的,我真的希望集群显示给定集群中每个单独标记的平均值以达到缩放级别。

这是我现在存在的代码:

folium_map = folium.Map(location=[33.97810188618428, -118.2155395906348]) 
mc = MarkerCluster() 
for p in points: 
    marker = build_folium_marker(p['f_name'], p['value'], p['lat'], p['lng']) 
    mc.add_child(marker) 
folium_map.add_children(mc) 
folium_map.save('folium_marker_cluster_map.html') 

在理想世界中,MarkerCluster 会采用一些参数让您发送“计数”或“平均”,但情况似乎并非如此。我持谨慎乐观的态度,有人将能够提出一个相当简单的修复方法,该修复方法不涉及 fork 传单(js 库 folium 建立在其上)和编辑 JS 源代码。我不可能是第一个想要在 MarkerClusters 上显示与总和不同的指标的人,特别是集群内标记值的平均值。

请您参考如下方法:

要自定义标记簇 icon_create_function 函数,以下示例演示如何覆盖标记标签以显示自定义值而不是默认值(簇中标记的计数):

icon_create_function = ''' 
    function(cluster) { 
        return L.divIcon({ 
             html: '<b>' + 123 + '</b>', 
             className: 'marker-cluster marker-cluster-small', 
             iconSize: new L.Point(20, 20) 
        }); 
    } 
''' 
 
marker_cluster = MarkerCluster(icon_create_function=icon_create_function) 

现在轮到通过标记传递自定义属性了,在 Folium 中默认标记不支持它,但是可以引入以下标记类来扩展 Marker 类:

class MarkerWithProps(Marker): 
    _template = Template(u""" 
        {% macro script(this, kwargs) %} 
        var {{this.get_name()}} = L.marker( 
            [{{this.location[0]}}, {{this.location[1]}}], 
            { 
                icon: new L.Icon.Default(), 
                {%- if this.draggable %} 
                draggable: true, 
                autoPan: true, 
                {%- endif %} 
                {%- if this.props %} 
                props : {{ this.props }}  
                {%- endif %} 
                } 
            ) 
            .addTo({{this._parent.get_name()}}); 
        {% endmacro %} 
        """) 
    def __init__(self, location, popup=None, tooltip=None, icon=None, 
                 draggable=False, props = None ): 
        super(MarkerWithProps, self).__init__(location=location,popup=popup,tooltip=tooltip,icon=icon,draggable=draggable) 
        self.props = json.loads(json.dumps(props)) 

现在在 Folium 中,一旦实例化了标记对象(其中 population 是自定义属性)

marker = MarkerWithProps( 
    location=marker_item['location'], 
    props = { 'population': marker_item['population']} 
) 
marker.add_to(marker_cluster) 

它的自定义属性可以通过 JavaScript 像这样访问:

var markers = cluster.getAllChildMarkers(); 
var sum = 0; 
for (var i = 0; i < markers.length; i++) { 
  sum += markers[i].options.props.population; 
} 

总而言之,这里有一个示例演示如何:

  • 通过标记传递自定义属性
  • 计算每个聚类标记的自定义标记属性的平均值
  • 显示集群标记的自定义标签

示例

#%% 
import json 
import folium 
from folium import Marker 
from folium.plugins import MarkerCluster 
from jinja2 import Template 
 
 
class MarkerWithProps(Marker): 
    _template = Template(u""" 
        {% macro script(this, kwargs) %} 
        var {{this.get_name()}} = L.marker( 
            [{{this.location[0]}}, {{this.location[1]}}], 
            { 
                icon: new L.Icon.Default(), 
                {%- if this.draggable %} 
                draggable: true, 
                autoPan: true, 
                {%- endif %} 
                {%- if this.props %} 
                props : {{ this.props }}  
                {%- endif %} 
                } 
            ) 
            .addTo({{this._parent.get_name()}}); 
        {% endmacro %} 
        """) 
    def __init__(self, location, popup=None, tooltip=None, icon=None, 
                 draggable=False, props = None ): 
        super(MarkerWithProps, self).__init__(location=location,popup=popup,tooltip=tooltip,icon=icon,draggable=draggable) 
        self.props = json.loads(json.dumps(props))     
 
 
 
map = folium.Map(location=[44, -73], zoom_start=4) 
 
marker_data =( 
    { 
        'location':[40.67, -73.94], 
        'population': 200      
    }, 
    { 
        'location':[44.67, -73.94], 
        'population': 300      
    } 
) 
 
icon_create_function = ''' 
    function(cluster) { 
        var markers = cluster.getAllChildMarkers(); 
        var sum = 0; 
        for (var i = 0; i < markers.length; i++) { 
            sum += markers[i].options.props.population; 
        } 
        var avg = sum/cluster.getChildCount(); 
 
        return L.divIcon({ 
             html: '<b>' + avg + '</b>', 
             className: 'marker-cluster marker-cluster-small', 
             iconSize: new L.Point(20, 20) 
        }); 
    } 
''' 
 
marker_cluster = MarkerCluster(icon_create_function=icon_create_function) 
 
for marker_item in marker_data: 
    marker = MarkerWithProps( 
        location=marker_item['location'], 
        props = { 'population': marker_item['population']} 
    ) 
    marker.add_to(marker_cluster) 
 
marker_cluster.add_to(map)     
 
#m.save(os.path.join('results', '1000_MarkerCluster0.html')) 
map 

结果