Adding Cesium app to Plotly Dash

Hi,

I’m trying to integrate Cesium into my Plotly Dash application but it doesn’t render the Cesium app in Plotly Dash when I run this locally from my Jupyter notebook. My python code is as follows:

import dash
import dash_html_components as html
external_css = ['https://cesium.com/downloads/cesiumjs/releases/1.76/Build/Cesium/Widgets/widgets.css']

app = dash.Dash(__name__, 
                title='Cesium Test',
                external_stylesheets=external_css)

app.layout = html.Div(id='blah',
                      children=[
                          'Testing...',
                          html.Script(src='https://cesium.com/downloads/cesiumjs/releases/1.76/Build/Cesium/Cesium.js'),
                          html.Div(id='cesiumContainer'),
                          html.Script('''
          Cesium.Ion.defaultAccessToken = 'any_code_works';
          var viewer = new Cesium.Viewer('cesiumContainer');
                          ''')
                      ])

if __name__ == '__main__':
    app.run_server(debug=True, use_reloader=False)

Here is a working example (Click on the “Show” button to see it renders the Cesium app):

html.Script tags are not executed by browsers when their code is added dynamically. There’s been some discussion about removing this and other components entirely (see eg here) but for now we’re following the lead of React and keeping it, despite it not working as you might expect.

My suggestion would be:
(1) add Cesium.js to external_scripts
(2) create a dummy clientside callback - based on cesiumContainer so you know it’ll only trigger when the container has been created - that instantiates the viewer. Something like:

app.clientside_callback(
    '''
    function(id) {
        Cesium.Ion.defaultAccessToken = 'any_code_works';
        var viewer = new Cesium.Viewer(id);
        return true;
    }
    ''',
    Output('cesiumContainer', 'data-done'),
    Input('cesiumContainer', 'id')
)

This works! Thanks! Here’s my updated code:

import dash
import dash_html_components as html
from dash.dependencies import Input, Output

external_css = ['https://cesium.com/downloads/cesiumjs/releases/1.76/Build/Cesium/Widgets/widgets.css']
external_scripts = [{'src':'https://cesium.com/downloads/cesiumjs/releases/1.76/Build/Cesium/Cesium.js'}]

app = dash.Dash(__name__, 
                title='Cesium Test',
                external_scripts=external_scripts,
                external_stylesheets=external_css)

app.layout = html.Div(id='blah',
                      children=[
                          'Testing...',
                          html.Div(id='cesiumContainer')
                      ])

app.clientside_callback(
    '''
    function(id) {
        Cesium.Ion.defaultAccessToken = "any_code_works";
        var viewer = new Cesium.Viewer(id);
        return true;
    }
    ''',
    Output('cesiumContainer', 'data-done'),
    Input('cesiumContainer', 'id')
)

if __name__ == '__main__':
    app.run_server(debug=True, use_reloader=False)

@nmill - are you able to pass data into cesium this way? If so, how?

@dcoley yes. I worked with CZML files. You can see working examples here:

https://oc-dash.herokuapp.com

And the source code is here:

Wow that’s awesome. Thanks for sharing. I really like functionality of the intercepts tab. Definitely looking into Cesium now.

Thanks

So cool!

1 Like