Home > Blockchain >  How to add arrows between interactive text labels in plotly?
How to add arrows between interactive text labels in plotly?

Time:04-29

I'm creating an app which is able to connect text labels in a simple manner like it enter image description here

I'm looking for plotly solutions at the moment since it has a support for dynamic HTML on Jupyter Notebook and allows to run it with no JavaScript. Moreover, I want to achieve these things:

  1. Functionality for accurate connection of rectangular text labels that are rectangular like it is shown in my diagram
  2. Interaction 1: make labels draggable with mouse
  3. Interaction 2: redraw arrows that connects text labels while dragging
  4. Interaction 3: redirect to some url after text label is double clicked

The most important for me is minimal working script of connection of rectangular text labels. matplotlib also supports enter image description here

Customising node, edge and label style

You'll need to define stylesheet parameter and uncomment it in app.layout definition:

stylesheet = [
    # Group selectors
    {'selector': 'node', 'style': {'content': 'data(label)', 'font-size': 8}},
    {'selector': 'edge',
     'style': {'content': 'data(label)',
               'curve-style': 'unbundled-bezier',
               'width': 1,
               'line-color': 'lightblue',
               'target-arrow-color': 'lightblue',
               'target-arrow-shape': 'triangle',
               'text-margin-x': 0,
               'font-size': 8}},

    # Class selectors
    {'selector': '.process',
     'style': {'shape': 'round-rectangle',
               'background-color': 'white',
               'border-color': 'black',
               'border-width': 1,
               'text-valign': 'center',
               'height': 40,
               'width': 75}}]

enter image description here

Navigation to url after node click

Based on this answer, just add a callback before server run:

@app.callback(
    Output("location", "href"),
    Input("cytoscape", "tapNodeData"),
    prevent_initial_call=True,
)

def navigate_to_url(node_data):
    return f"https://en.wikipedia.org/wiki/{node_data['label']}"

Support for Jupyter Notebook

For embedding app inside Jupyter Notebook, use JupyterDash. It's simple, the only think you need is to use a different kind of app:

from jupyter_dash import JupyterDash
...
if __name__ == '__main__':
    app.run_server(mode='inline')

Support for GitHub and nbviewer

If you upload your app in GitHub it won't display interactive apps but you could load your GitHub link in nbviewer. There are two bad sides:

  • It won't load unless you replace your link https://... of nbviewer with http://.... I'm not satisfied but this is the only workaround I could find.
  • It won't load multiple apps in one notebook.

Support for Latex

There was no straight way in Dash Plotly to render Mathjax until release of Dash v2.3.0 one month ago. It's still not supported in Dash Cytoscape which I've been using in these apps. I hope this issue is going to be resolved in near future.

Text enclosing in rectangular labels that fits it's shape.

I could find any way to do it yet as you could see in an example of node with 'Very long line for testing'. At the moment, if text labels occurs to be long, a better design is to use circular nodes with text above.


I'm glad I was able to find solutions to majority of my questions and I'm still open to discuss about support for LaTeX/Mathjax, nbviewer and better text enclosion in labels.

  • Related