大叶中线的动态样式

问题描述 投票:0回答:1

我一直试图从folium的TimestampedGeoJson插件中弄清楚。

我想绘制随时间改变颜色的线。目前,我要做的是每次需要更改颜色时都要完全重画一条线,这需要大量的开销。

另一个问题是如何在功能中指定时间。目前,我有这个例子:

import folium
from folium.plugins import TimestampedGeoJson

m = folium.Map(
    location=[42.80491692, -4.62577249],
    zoom_start=10
)

data = [
{
    'coordinates': [
        [-4.018876661, 43.11843382],
        [-4.856537491, 42.82202193],
    ],
    'dates': [
        '2017-06-02T00:00:00',
        '2017-06-02T00:10:00'
    ],
    'color': 'red'
},
{
    'coordinates': [
        [-4.018876661, 43.11843382],
        [-4.856537491, 42.82202193],
    ],
    'dates': [
        '2017-06-02T00:00:00',
        '2017-06-02T00:20:00'
    ],
    'color': 'blue'
},
]

features = [
    {
        'type': 'Feature',
        'geometry': {
            'type': 'LineString',
            'coordinates': d['coordinates'],
        },
        'properties': {
            'times': d['dates'],
            'style': {
                'color': d['color'],
                'weight': d['weight'] if 'weight' in d else 5
            }
        }
    }
    for d in data
]

TimestampedGeoJson({
    'type': 'FeatureCollection',
    'features': features,
}, period='PT1M', add_last_point=True).add_to(m)

m.save('dynamic4.html')

对我来说,第一个日期没有任何意义,但显然是必需的,因为否则浏览器将不会绘制任何内容。

所以:

a)如何在不重画线条的情况下更改样式?b)时间是什么意思?如何指定一致的时间顺序?

python leaflet folium
1个回答
0
投票

我将首先尝试单独解决您的问题,我将为最终的工作提供完整的解决方案。本质上:

  1. 更改TimestampedGeoJson _template变量以更改style_function,它将使它具有动态风格
  2. 确保在TimestampedGeoJson数据中每个坐标具有一个时间步长
  3. 为避免混淆,请尝试在一定的时间步中不要重叠要素或使要素缺少的数据
  4. 我相信在您的情况下,您只有一项功能,但是会在不同的时间步长更改颜色

解决您的问题:

a)如何在不重新绘制线条的情况下更改样式?

我认为从叶子本身来看是不可能的,有必要将style_function传递给TimestampedGeoJson,该函数目前甚至不是类init的参数。这样做似乎很难,因为您需要将python style_function转换为javascript style_function。

将有一个简单的解决方法。在class definition of TimestampedGeoJson内部,它使用_template变量作为javascript代码的字符串模板,因此您可以根据需要使用JavaScript来适应此模板。

class TimestampedGeoJson(MacroElement):
         .... hidding lines to save space
    _template = Template("""
        {% macro script(this, kwargs) %}
                 .... hidding lines to save space
                    style: function (feature) {
                        return feature.properties.style;
                    },
                    onEachFeature: function(feature, layer) {
                        if (feature.properties.popup) {
                        layer.bindPopup(feature.properties.popup);
                        }
                    }
                })
        {% endmacro %}
        """)  # noqa
     ..... hidding lines to save space

因此,为了在每一步更改线条颜色,您可以更改模板的这一部分:

style: function (feature) {
                        return feature.properties.style;
                    },

通过此方法:遍历颜色数组

                    style: function(feature) {
                        lastIdx=feature.properties.colors.length-1
                        currIdx=feature.properties.colors.indexOf(feature.properties.color);
                        if(currIdx==lastIdx){
                            feature.properties.color = feature.properties.colors[0]  
                        }
                        else{
                            feature.properties.color =feature.properties.colors[currIdx+1] 
                        }
                        return {color: feature.properties.color}
                    },

更改它,以便您每时每刻更新properties.style内部的颜色。

b)时间是什么意思?如何指定一致的时间顺序?

[TimestampedGeoJson使用的是库Leaflet.TimeDimension,因此TimestampedGeoJson对应于L.TimeDimension.Layer.GeoJSON

从该文档中您可以得到

“ coordTimes,time或linestringTimestamps:可以与几何关联的时间数组(日期字符串或ms)。对于LineString,它必须具有与LineString中的坐标一样多的项目。”] >

因此从本质上讲,只要确保一致1.对于每个要素,时间的大小与坐标相同,并且2.使用有效的日期字符串或ms格式3.如果您的日期不断增加,则将期间设置为该值

总而言之,在您之前的示例中,我主要进行了更改:1)使用新的style_function添加了_template变量,并更改了TimestampedGeoJson默认模板

2)稍微改变了两个特征的坐标,以显示您设置的两个特征是重叠的,并且在某些时间步长上,在某些时间步长上,仅定义了第一个特征,后来又定义了第二个特征,因此它使正在发生的事情变得混乱每个时间步骤。

3)为每个功能添加了要循环显示的颜色列表>

from jinja2 import Template
_template = Template("""
    {% macro script(this, kwargs) %}
        L.Control.TimeDimensionCustom = L.Control.TimeDimension.extend({
            _getDisplayDateFormat: function(date){
                var newdate = new moment(date);
                console.log(newdate)
                return newdate.format("{{this.date_options}}");
            }
        });
        {{this._parent.get_name()}}.timeDimension = L.timeDimension(
            {
                period: {{ this.period|tojson }},
            }
        );
        var timeDimensionControl = new L.Control.TimeDimensionCustom(
            {{ this.options|tojson }}
        );
        {{this._parent.get_name()}}.addControl(this.timeDimensionControl);
        var geoJsonLayer = L.geoJson({{this.data}}, {
                pointToLayer: function (feature, latLng) {
                    if (feature.properties.icon == 'marker') {
                        if(feature.properties.iconstyle){
                            return new L.Marker(latLng, {
                                icon: L.icon(feature.properties.iconstyle)});
                        }
                        //else
                        return new L.Marker(latLng);
                    }
                    if (feature.properties.icon == 'circle') {
                        if (feature.properties.iconstyle) {
                            return new L.circleMarker(latLng, feature.properties.iconstyle)
                            };
                        //else
                        return new L.circleMarker(latLng);
                    }
                    //else
                    return new L.Marker(latLng);
                },
                style: function(feature) {
                    lastIdx=feature.properties.colors.length-1
                    currIdx=feature.properties.colors.indexOf(feature.properties.color);
                    if(currIdx==lastIdx){
                        feature.properties.color = feature.properties.colors[currIdx+1] 
                    }
                    else{
                        feature.properties.color =feature.properties.colors[currIdx+1] 
                    }
                    return {color: feature.properties.color}
                },
                onEachFeature: function(feature, layer) {
                    if (feature.properties.popup) {
                    layer.bindPopup(feature.properties.popup);
                    }
                }
            })
        var {{this.get_name()}} = L.timeDimension.layer.geoJson(
            geoJsonLayer,
            {
                updateTimeDimension: true,
                addlastPoint: {{ this.add_last_point|tojson }},
                duration: {{ this.duration }},
            }
        ).addTo({{this._parent.get_name()}});
    {% endmacro %}
    """)
import folium
from folium.plugins import TimestampedGeoJson

m = folium.Map(
    location=[42.80491692, -4.62577249],
    zoom_start=9
)

data = [
{
    'coordinates': [
        [-4.018876661, 43.11843382],
        [-4.856537491, 42.82202193],
    ],
    'dates': [
        '2017-06-02T00:00:00',
        '2017-06-02T00:10:00'
    ],
    'color': 'brown',
    'colors':["black","orange","pink"],
},
{
    'coordinates': [
        [-4.058876661, 43.11843382],
        [-4.936537491, 42.82202193],
    ],
    'dates': [
        '2017-06-02T00:00:00',
        '2017-06-02T00:10:00'
    ],
    'color': 'blue',
    'colors':["red","yellow","green"],
},
]

features = [
    {
        'type': 'Feature',
        'geometry': {
            'type': 'LineString',
            'coordinates': d['coordinates'],
        },
        'properties': {
            'times': d['dates'],
            'color': d["color"],
            'colors':d["colors"]
        }
    }
    for d in data
]

t=TimestampedGeoJson({
    'type': 'FeatureCollection',
    'features': features,
}, period='PT10H', add_last_point=True)
t._template=_template
t.add_to(m)

m.save('original.html')
© www.soinside.com 2019 - 2024. All rights reserved.