naranara
naranara

Reputation: 179

Add popup in dl.GeoJSON Dash-leaflet (Python/Dash)

I have been using dash-leaflet for 1 month and it is a good library for showing interactive map with filter widget in dash. But I have question, how do I add popup in polygon? especially in dl.GeoJSON one?

Here is my code

import dash
from dash import Dash, html, dcc
from dash.dependencies import Input, Output
import dash_mantine_components as dmc
import dash_leaflet as dl

from dash_extensions.javascript import arrow_function

import geopandas as gpd
import json
from statistics import mean

all_blocks = gpd.read_file('GeoJSON Files/blocks.geojson')

# -------------------------------------Dash Apps----------------------------------------

app = Dash(__name__, meta_tags=[
        {"name": "viewport", "content": "width=device-width, initial-scale=1"}
    ])

app.layout = html.Section([
    html.Div(children=[
        html.H5('Block Name'),
        dmc.MultiSelect(
            placeholder="Select Block Name",
            id="multiselect-block",
            value=all_blocks['Block_Name'].unique().tolist(),
            data=all_blocks['Block_Name'].unique().tolist(),
            style={'marginTop':10},
            clearable=True,
            searchable=True,
            nothingFound= 'No Options Found'
            )
    ]),
    
    html.Div(id='output-map')
    ])

@app.callback(
    Output('output-map','children'),
    Input('multiselect-block','value'),
    Input('multiselect-block','data')
)

def plot_map(block_submitted_value, block_submitted_data):
    edited_layer= all_blocks[(all_blocks['Block_Name'].isin(block_submitted_value)) & (all_blocks['Block_Name'].isin(block_submitted_data))]
    
    #defining dl.GeoJSON for filtered edited_layer
    layer_blocks = dl.GeoJSON(id='block_load',
                            data=json.loads(edited_layer.to_json()),
                            hoverStyle=arrow_function(dict(weight=6, fillColor='#45b6fe', fillOpacity=0.5)),
                            options=dict(style={'color':'#3a9bdc',
                                        'weight':2,
                                        'dashArray':'30, 10',
                                        'dashOffset':'1',
                                        'opacity':1,
                                        }))
    bounds = edited_layer.total_bounds
    x = mean([bounds[0], bounds[2]])
    y = mean([bounds[1], bounds[3]])
    location = (y, x)
    
    if edited_layer.empty:
        return dl.Map(children=[dl.TileLayer(url='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'),
                        dl.GestureHandling(),
                        dl.MeasureControl(position="topleft", primaryLengthUnit="kilometers", primaryAreaUnit="hectares",
                                        activeColor="#C29200", completedColor="#972158")],
                        center=[5.3, 96.3],
                        zoom=11,
                        style={
                            'z-index':'0',
                            'width': '1750px',
                            'height': '965px',
                            'marginLeft':'20px',
                        })

    return dl.Map(children=[dl.GeoJSON(layer_blocks),
                dl.TileLayer('url=https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'),
                dl.GestureHandling(),
                dl.MeasureControl(position="topleft", primaryLengthUnit="kilometers", primaryAreaUnit="hectares",
                                activeColor="#C29200", completedColor="#972158")],
                center=[y, x],
                zoom=11,
                style={
                    'z-index':'0',
                    'width': '99%',
                    'height': '965px',
                    'marginLeft':'20px',
                    'float':'right'
                })

if __name__ == '__main__':
    app.run_server(debug=True, port = 8400)

Here is my dummy data, it is in GeoJSON format

{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"Block_Name":"East-Block","Status":"Production","Operator":"A","num_wells":20,"sq_km":145.97,"est_reserve":100},"geometry":{"coordinates":[[[96.4001057373053,5.208656351062942],[96.43375136718726,5.221648609300516],[96.46259047851515,5.23737571951817],[96.46121718750072,5.279084831409563],[96.35684707031174,5.279768564031215],[96.35753371582075,5.340617736210092],[96.26140334472717,5.341985064196123],[96.26140334472717,5.261307518914151],[96.32663466796942,5.23053789406255],[96.4001057373053,5.208656351062942]]],"type":"Polygon"}},{"type":"Feature","properties":{"Block_Name":"West-Block","Status":"Production","Operator":"B","num_wells":50,"sq_km":171.38,"est_reserve":420},"geometry":{"coordinates":[[[96.1500638674625,5.274467547614364],[96.14897384519247,5.419171436272961],[96.01490110586337,5.42134172287426],[96.01526444661994,5.383360416138984],[96.07521567152321,5.3826369393847955],[96.07557901227983,5.355867695999478],[96.03488484749829,5.355867696870973],[96.03452150673985,5.334162042989206],[96.0501451592911,5.327288425995064],[96.06431544881394,5.305219978512483],[96.07812239757834,5.292557397961701],[96.10500961359554,5.285683317057433],[96.13117014809939,5.279894558164472],[96.14025366702509,5.278809159853225],[96.1500638674625,5.274467547614364]]],"type":"Polygon"}},{"type":"Feature","properties":{"Block_Name":"South-Block","Status":"Exploration","Operator":"A","num_wells":0,"sq_km":48.74,"est_reserve":150},"geometry":{"coordinates":[[[96.15020619743746,5.321413143458614],[96.15075239154925,5.274369183512903],[96.15921840028875,5.269746173698309],[96.19062456174476,5.259684209917438],[96.21137993801023,5.259140315346897],[96.23814344951205,5.262403675642247],[96.26108360222605,5.263763404046799],[96.26108360222605,5.320325462349771],[96.15020619743746,5.321413143458614]]],"type":"Polygon"}},{"type":"Feature","properties":{"Block_Name":"Center-Block","Status":"Exploration","Operator":"C","num_wells":0,"sq_km":48.98,"est_reserve":120},"geometry":{"coordinates":[[[96.14996393515247,5.321933704052],[96.26084133994107,5.320846023863609],[96.26138753405411,5.3417835292513445],[96.35451363019473,5.340967795663914],[96.35451363019473,5.36924592531598],[96.29224750139701,5.369789722668301],[96.29197440434115,5.401329137491388],[96.33922019505121,5.401057252985197],[96.33922019505121,5.419001368471612],[96.14887154692752,5.419545121233369],[96.14996393515247,5.321933704052]]],"type":"Polygon"}},{"type":"Feature","properties":{"Block_Name":"North-Block","Status":"Production","Operator":"A","num_wells":30,"sq_km":64.55,"est_reserve":220},"geometry":{"coordinates":[[[96.08469351270912,5.419774728990944],[96.21141054675434,5.419774728990944],[96.33102705734086,5.41868722339008],[96.33048086322776,5.43826202425123],[96.24745935816333,5.438805759641596],[96.24745935816333,5.451311537935112],[96.30644832228882,5.451855261522326],[96.30590212817572,5.467079321826603],[96.15952210608873,5.466535612046528],[96.16006830020183,5.439893228949643],[96.08523970682091,5.440980696292215],[96.08469351270912,5.419774728990944]]],"type":"Polygon"}}]}

I want to show the pop up whenever I click the polygon, just like in Folium, and in the form of HTML like this enter image description here

How do I do that in Dash-Leaflet? Any help would appreciate, thanks!

Upvotes: 1

Views: 489

Answers (1)

emher
emher

Reputation: 6024

If you just need to display a simple popup, you can add a feature property named popup, and it will be rendered as a popup automatically,

from dash import Dash
import dash_leaflet as dl
import dash_leaflet.express as dlx

app = Dash()
app.layout = dl.Map([
    dl.TileLayer(),
    dl.GeoJSON(data=dlx.dicts_to_geojson([dict(lat=56, lon=10, tooltip="Hello world!")])),
], center=[56,10], zoom=6, style={'height': '50vh'})

if __name__ == '__main__':
    app.run_server()

If you need further customization, you can pass a custom JavaScript function via the onEachFeature property of the GeoJSON component function, which binds the custom popup,

from dash import Dash
from dash_extensions.javascript import assign
import dash_leaflet as dl
import dash_leaflet.express as dlx

on_each_feature = assign("""function(feature, layer, context){
    layer.bindTooltip(`This is <b> html </b>. Foo is [${feature.properties.foo}])`)
}""")  # add custom tooltip. Must be done in JavaScript
app = Dash()
app.layout = dl.Map([
    dl.TileLayer(),
    dl.GeoJSON(data=dlx.dicts_to_geojson([dict(lat=56, lon=10, foo="Hello world!")]),
               onEachFeature=on_each_feature),
], center=[56, 10], zoom=6, style={'height': '50vh'})

if __name__ == '__main__':
    app.run_server()

Upvotes: 0

Related Questions