1
votes

It seems that this should be fairly straightforward, but I am attempting to overlay text annotations on a dcc.Graph component. I have a dictionary of coordinates that specify the locations of the annotations on the plot, and I am also including shapes defined by SVG paths. I would like all of the annotations (as a baseline use case) to have black text (#000000), but it appears that they are being rendered behind the shapes themselves. Is there a current means to ensure they are brought to the front?

Here is a minimal working example:

import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go

labels = {'Point 1': (3.5,5), 'Point 2': (1.5,2), 'Point 3': (3.5,8)}
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([

    html.H1('Test', id='test', style={'margin': 50}),

    dcc.Graph(id='my-plot', style={'margin': 10}),

])

@app.callback(
    Output('my-plot', 'figure'),
    [Input('test', 'children')])
def update_graph(val):

    return {

        'data': [go.Scatter(
            x=[v[0]],
            y=[v[1]],
            text=k,
            mode='text'
        ) for k, v in labels.items()],

        'layout': go.Layout(
            margin={'l': 40, 'b': 40, 't': 40, 'r': 40},
            shapes=[
                {
                    'type': 'path',
                    'path': ' M 1 1 L 1 3 L 4 1 Z',
                    'fillcolor': 'rgba(44, 160, 101, 0.5)',
                    'line': {
                        'color': 'rgb(44, 160, 101)',
                    }
                },
                {
                    'type': 'path',
                    'path': ' M 3,7 L2,8 L2,9 L3,10, L4,10 L5,9 L5,8 L4,7 Z',
                    'fillcolor': 'rgba(255, 140, 184, 0.5)',
                    'line': {
                        'color': 'rgb(255, 140, 184)',
                    }
                },
            ]
        )
    }

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

See below, where the fill color of the shapes modifies the rendered color of the text annotations:

enter image description here

1
Did you try 'layer': 'below' for your shapes? - Maximilian Peters
You're a savior, I really don't know how I missed that in the docs. Post as answer and I'll accept. Much appreciated. - rahlf23

1 Answers

1
votes

Adding 'layer': 'below' to each element of shapes will move the shape to the background, i.e. the label text will be in the foreground and also the grid lines.

enter image description here

[...]

shapes=[{'layer': 'below',
         'type': 'path',
         'path': ' M 1 1 L 1 3 L 4 1 Z',
         'fillcolor': 'rgba(44, 160, 101, 0.5)',
         'line': {'color': 'rgb(44, 160, 101)'}
        },
        {'layer': 'below',
         'type': 'path',
         'path': ' M 3,7 L2,8 L2,9 L3,10, L4,10 L5,9 L5,8 L4,7 Z',
         'fillcolor': 'rgba(255, 140, 184, 0.5)',
         'line': {'color': 'rgb(255, 140, 184)'}
        }
       ]

[...]