Using VantaJS (3rd party js library) with dash

Here’s an approach using a clientside callback based on an answer in a different thread from @RenaudLN. Because the callback is triggered once the layout has been rendered, you can use it to defer execution of JS until Dash has finished loading.

Note that when I first implemented this the use of html.Canvas was giving me some problems. Changing it to html.Div helped.

# app.py
import dash
import dash_bootstrap_components as dbc
from dash import ClientsideFunction, Input, Output, html

app = dash.Dash(
    __name__,
    external_stylesheets=[
        "https://fonts.googleapis.com/css?family=Poppins",
        dbc.themes.MINTY,
    ],
    external_scripts=[
        "https://cdnjs.cloudflare.com/ajax/libs/three.js/r121/three.min.js",
        "https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.cells.min.js",
    ],
)

app.layout = html.Div(
    children=[
        html.Div(
            dbc.Container(
                html.H1(
                    "Demo Dash app with Vanta.JS", style={"color": "#ff3d3d"}
                ),
                className="py-5",
            ),
            id="vanta-container",
            style={"height": "100vh", "width": "100vw"},
        ),
    ],
)

app.clientside_callback(
    ClientsideFunction(namespace="clientside", function_name="attach_vanta"),
    Output("vanta-container", "id"),
    [Input("vanta-container", "id")],
)

if __name__ == "__main__":
    app.run_server(debug=True)

and in assets/

// assets/custom.js
if (!window.dash_clientside) {
  window.dash_clientside = {};
}
window.dash_clientside.clientside = {
  attach_vanta: function (id) {
    setTimeout(function () {
      var el = document.getElementById(id);
      VANTA.CELLS({ el });
    }, 1);
    return window.dash_clientside.no_update;
  },
};
2 Likes