通过 hideout [geojson] 的 dash-leaflet 过滤和样式
dash-leaflet filtering and styling via hideout [geojson]
我想filter and style via hideout property like on docs site,但想不通。
现在,我被困在这里:
import dash_html_components as html
import dash_leaflet as dl
import dash_core_components as dcc
import dash_leaflet.express as dlx
from dash import Dash
from dash.dependencies import Output, Input
from dash_extensions.javascript import assign
# A few cities in Denmark.
cities = [dict(name="Aalborg", lat=57.0268172, lon=9.837735),
dict(name="Aarhus", lat=56.1780842, lon=10.1119354),
dict(name="Copenhagen", lat=55.6712474, lon=12.5237848)]
# Create drop down options.
dd_options = [dict(value=c["name"], label=c["name"]) for c in cities]
dd_defaults = [o["value"] for o in dd_options]
# Generate geojson with a marker for each city and name as tooltip.
geojson = dlx.dicts_to_geojson([{**c, **dict(tooltip=c['name'])} for c in cities])
# Create javascript function that filters on feature name.
geojson_filter = assign("function(feature, context){console.log(context); return context.props.hideout.dd_defaults.includes(feature.properties.name);}")
# Create example app.
app = Dash()
app.layout = html.Div([
dl.Map(children=[
dl.TileLayer(),
dl.GeoJSON(data=geojson, options=dict(filter=geojson_filter), hideout=dict(dd_defaults=dd_defaults, test="test"), id="geojson", zoomToBounds=True)
], style={'width': '100%', 'height': '50vh', 'margin': "auto", "display": "block"}, id="map"),
dcc.Dropdown(id="dd", value=dd_defaults, options=dd_options, clearable=False, multi=True)
])
# Link drop down to geojson hideout prop (could be done with a normal callback, but clientside is more performant).
app.clientside_callback(
"""function(value, hideout){
hideout.dd_defaults = value
console.log(hideout);
return hideout
;}
""",
Output("geojson", "hideout"), Input("dd", "value"), Input("geojson", "hideout"))
if __name__ == '__main__':
app.run_server()
我认为当我传回整个藏身处组件时它应该起作用,但它不起作用。是错误还是我做错了什么?问题似乎是当我将字典传递给 hideout 组件时。
好的,我修复一次!我需要这样 return:
app.clientside_callback(
"""
function(value, hideout) {
console.log(hideout);
return {
dd_defaults: value
}
;}
""",
Output("geojson", "hideout"), Input("dd", "value"), Input("geojson", "hideout"))
好的,有一个完整的例子:
import dash_html_components as html
import dash_leaflet as dl
import dash_leaflet.express as dlx
import dash_core_components as dcc
from dash import Dash
from dash_extensions.javascript import arrow_function, assign
from dash.dependencies import Output, Input
def get_info(feature=None):
header = [html.H4("US Population Density")]
if not feature:
return header + [html.P("Hoover over a state")]
return header + [html.B(feature["properties"]["name"]), html.Br(),
"{:.3f} people / mi".format(feature["properties"]["density"]), html.Sup("2")]
classes = [0, 10, 20, 50, 100, 200, 500, 1000]
colorscale = ['#FFEDA0', '#FED976', '#FEB24C', '#FD8D3C', '#FC4E2A', '#E31A1C', '#BD0026', '#800026']
style = dict(weight=2, opacity=1, color='white', dashArray='3', fillOpacity=0.7)
# Create colorbar.
ctg = ["{}+".format(cls, classes[i + 1]) for i, cls in enumerate(classes[:-1])] + ["{}+".format(classes[-1])]
colorbar = dlx.categorical_colorbar(categories=ctg, colorscale=colorscale, width=300, height=30, position="bottomleft")
# Geojson rendering logic, must be JavaScript as it is executed in clientside.
style_handle = assign("""function(feature, context){
const {classes, colorscale, style, colorProp} = context.props.hideout; // get props from hideout
const value = feature.properties[colorProp]; // get value the determines the color
for (let i = 0; i < classes.length; ++i) {
if (value > classes[i]) {
style.fillColor = colorscale[i]; // set the fill color according to the class
}
}
return style;
}""")
filter_handle = assign("function(feature, context){console.log(context);return context.props.hideout.name.includes(feature.properties.name);}")
dd_options = [{"value": "Alabama", "label": "Alabama"}, {"value": "Arkansas", "label": "Arkansas"}, {"value": "Florida", "label": "Florida"}]
dd_defaults = ["Alabama", "Arkansas", "Florida"]
# Create geojson.
geojson = dl.GeoJSON(url="/assets/us-states.json", # url to geojson file
options=dict(style=style_handle,filter=filter_handle), # how to style each polygon
zoomToBounds=True, # when true, zooms to bounds when data changes (e.g. on load)
zoomToBoundsOnClick=True, # when true, zooms to bounds of feature (e.g. polygon) on click
hoverStyle=arrow_function(dict(weight=5, color='#666', dashArray='')), # style applied on hover
hideout=dict(colorscale=colorscale, classes=classes, style=style, colorProp="density", name=dd_defaults),
id="geojson")
# Create info control.
info = html.Div(children=get_info(), id="info", className="info",
style={"position": "absolute", "top": "10px", "right": "10px", "z-index": "1000"})
# Create app.
app = Dash(prevent_initial_callbacks=True)
app.layout = html.Div([
dl.Map([dl.TileLayer(), geojson, colorbar, info], style={'width': '100%', 'height': '50vh', 'margin': "auto", "display": "block"}, id="map"
),
html.Div([
dcc.Dropdown(id="dd", value=dd_defaults, options=dd_options, clearable=False, multi=True)
])
])
@app.callback(Output("info", "children"), [Input("geojson", "hover_feature")])
def info_hover(feature):
return get_info(feature)
app.clientside_callback("""
function(x, y){
return {
classes: y.classes,
name: x,
colorProp: y.colorProp,
colorscale: y.colorscale,
style: y.style
};}
""",
Output("geojson", "hideout"), [Input("dd", "value"), Input("geojson", "hideout")]),
if __name__ == '__main__':
app.run_server()
我想filter and style via hideout property like on docs site,但想不通。
现在,我被困在这里:
import dash_html_components as html
import dash_leaflet as dl
import dash_core_components as dcc
import dash_leaflet.express as dlx
from dash import Dash
from dash.dependencies import Output, Input
from dash_extensions.javascript import assign
# A few cities in Denmark.
cities = [dict(name="Aalborg", lat=57.0268172, lon=9.837735),
dict(name="Aarhus", lat=56.1780842, lon=10.1119354),
dict(name="Copenhagen", lat=55.6712474, lon=12.5237848)]
# Create drop down options.
dd_options = [dict(value=c["name"], label=c["name"]) for c in cities]
dd_defaults = [o["value"] for o in dd_options]
# Generate geojson with a marker for each city and name as tooltip.
geojson = dlx.dicts_to_geojson([{**c, **dict(tooltip=c['name'])} for c in cities])
# Create javascript function that filters on feature name.
geojson_filter = assign("function(feature, context){console.log(context); return context.props.hideout.dd_defaults.includes(feature.properties.name);}")
# Create example app.
app = Dash()
app.layout = html.Div([
dl.Map(children=[
dl.TileLayer(),
dl.GeoJSON(data=geojson, options=dict(filter=geojson_filter), hideout=dict(dd_defaults=dd_defaults, test="test"), id="geojson", zoomToBounds=True)
], style={'width': '100%', 'height': '50vh', 'margin': "auto", "display": "block"}, id="map"),
dcc.Dropdown(id="dd", value=dd_defaults, options=dd_options, clearable=False, multi=True)
])
# Link drop down to geojson hideout prop (could be done with a normal callback, but clientside is more performant).
app.clientside_callback(
"""function(value, hideout){
hideout.dd_defaults = value
console.log(hideout);
return hideout
;}
""",
Output("geojson", "hideout"), Input("dd", "value"), Input("geojson", "hideout"))
if __name__ == '__main__':
app.run_server()
我认为当我传回整个藏身处组件时它应该起作用,但它不起作用。是错误还是我做错了什么?问题似乎是当我将字典传递给 hideout 组件时。
好的,我修复一次!我需要这样 return:
app.clientside_callback(
"""
function(value, hideout) {
console.log(hideout);
return {
dd_defaults: value
}
;}
""",
Output("geojson", "hideout"), Input("dd", "value"), Input("geojson", "hideout"))
好的,有一个完整的例子:
import dash_html_components as html
import dash_leaflet as dl
import dash_leaflet.express as dlx
import dash_core_components as dcc
from dash import Dash
from dash_extensions.javascript import arrow_function, assign
from dash.dependencies import Output, Input
def get_info(feature=None):
header = [html.H4("US Population Density")]
if not feature:
return header + [html.P("Hoover over a state")]
return header + [html.B(feature["properties"]["name"]), html.Br(),
"{:.3f} people / mi".format(feature["properties"]["density"]), html.Sup("2")]
classes = [0, 10, 20, 50, 100, 200, 500, 1000]
colorscale = ['#FFEDA0', '#FED976', '#FEB24C', '#FD8D3C', '#FC4E2A', '#E31A1C', '#BD0026', '#800026']
style = dict(weight=2, opacity=1, color='white', dashArray='3', fillOpacity=0.7)
# Create colorbar.
ctg = ["{}+".format(cls, classes[i + 1]) for i, cls in enumerate(classes[:-1])] + ["{}+".format(classes[-1])]
colorbar = dlx.categorical_colorbar(categories=ctg, colorscale=colorscale, width=300, height=30, position="bottomleft")
# Geojson rendering logic, must be JavaScript as it is executed in clientside.
style_handle = assign("""function(feature, context){
const {classes, colorscale, style, colorProp} = context.props.hideout; // get props from hideout
const value = feature.properties[colorProp]; // get value the determines the color
for (let i = 0; i < classes.length; ++i) {
if (value > classes[i]) {
style.fillColor = colorscale[i]; // set the fill color according to the class
}
}
return style;
}""")
filter_handle = assign("function(feature, context){console.log(context);return context.props.hideout.name.includes(feature.properties.name);}")
dd_options = [{"value": "Alabama", "label": "Alabama"}, {"value": "Arkansas", "label": "Arkansas"}, {"value": "Florida", "label": "Florida"}]
dd_defaults = ["Alabama", "Arkansas", "Florida"]
# Create geojson.
geojson = dl.GeoJSON(url="/assets/us-states.json", # url to geojson file
options=dict(style=style_handle,filter=filter_handle), # how to style each polygon
zoomToBounds=True, # when true, zooms to bounds when data changes (e.g. on load)
zoomToBoundsOnClick=True, # when true, zooms to bounds of feature (e.g. polygon) on click
hoverStyle=arrow_function(dict(weight=5, color='#666', dashArray='')), # style applied on hover
hideout=dict(colorscale=colorscale, classes=classes, style=style, colorProp="density", name=dd_defaults),
id="geojson")
# Create info control.
info = html.Div(children=get_info(), id="info", className="info",
style={"position": "absolute", "top": "10px", "right": "10px", "z-index": "1000"})
# Create app.
app = Dash(prevent_initial_callbacks=True)
app.layout = html.Div([
dl.Map([dl.TileLayer(), geojson, colorbar, info], style={'width': '100%', 'height': '50vh', 'margin': "auto", "display": "block"}, id="map"
),
html.Div([
dcc.Dropdown(id="dd", value=dd_defaults, options=dd_options, clearable=False, multi=True)
])
])
@app.callback(Output("info", "children"), [Input("geojson", "hover_feature")])
def info_hover(feature):
return get_info(feature)
app.clientside_callback("""
function(x, y){
return {
classes: y.classes,
name: x,
colorProp: y.colorProp,
colorscale: y.colorscale,
style: y.style
};}
""",
Output("geojson", "hideout"), [Input("dd", "value"), Input("geojson", "hideout")]),
if __name__ == '__main__':
app.run_server()