Annotations with border and rounded corner

Hey guys,

Is there a simple way to add annotations with a border whose corners would be rounded, on a figure?

Eg of an annotation with standard rectangular border:

fig=go.Figure()
fig.add_annotation(    
    yref="paper", xref="x", x=0.5, y=0.5, text="some text to display",
    showarrow=True, align="center", arrowhead=2, arrowsize=1, arrowwidth=1,
    ax=0, ay=5, borderwidth=0.5, borderpad=2, bordercolor="black",
    yanchor="top", bgcolor="pink", font=dict(color="black", weight="bold", size=10)
)
fig.show()

When inspecting the doc we see this:

<g class="annotation-text-g" transform="rotate(0,403.64,555)">
<g class="cursor-pointer" transform="translate(359,547)">
<rect class="bg" x="0.25" y="0.25" width="89.5" height="15.5" style="stroke-width: 0.5px; stroke: rgb(0, 0, 0); stroke-opacity: 1; fill: rgb(255, 192, 203); fill-opacity: 1;"></rect>
<text class="annotation-text" text-anchor="middle" data-unformatted="some text to display" data-math="N" x="44.5810546875" y="11.2998046875" style="font-family: LardySerif-Regular; font-size: 10px; fill: rgb(0, 0, 0); fill-opacity: 1; font-weight: bold; font-style: normal; font-variant: normal; white-space: pre;">some text to display</text>
</g>
</g>

The desired output would be this:

<g class="annotation-text-g" transform="rotate(0,403.64,555)">
<g class="cursor-pointer" transform="translate(359,547)">
<rect class="bg" x="0.25" y="0.25" width="89.5" height="15.5" style="stroke-width: 0.5px; stroke: rgb(0, 0, 0); stroke-opacity: 1; fill: rgb(255, 192, 203); fill-opacity: 1;" rx="10" ry="10"></rect>
<text class="annotation-text" text-anchor="middle" data-unformatted="some text to display" data-math="N" x="44.5810546875" y="11.2998046875" style="font-family: LardySerif-Regular; font-size: 10px; fill: rgb(0, 0, 0); fill-opacity: 1; font-weight: bold; font-style: normal; font-variant: normal; white-space: pre;">some text to display</text>
</g>
</g>

But, for this, we would need:

  1. an option to pass rx and ry value to the .fig_annotation, used when there is a border around the text. Maybe in relative terms instead of px ? (like, % of height or % of font size + vertical padding?)
  2. an option to adjust the horizontal padding a bit too. Currently we only have “borderpad”, whose value seems applied to the top, bottom, left and right padding values.

Is it better to use add_shape with “label”, and define a SVG path of some kind ? Anyone ever tried to add annotations whose borders would have rounded corners?

Hi @David22 , If I’m right Plotly annotations do not support rounded corners for their borders. The borderpad attribute allows padding, and bordercolor/borderwidth customize the border, but there’s no native option for border-radius or similar CSS-style rounded corners.

You can overlay an html.Div styled with CSS (including border-radius) instead of using Plotly’s built-in annotations. like this:

from dash import Dash, html, dcc
import plotly.graph_objs as go

app = Dash()

fig=go.Figure()

app.layout = html.Div([
    html.Div(
        children=[
            dcc.Graph(
                id="my-plot",
                figure=fig,
                style={"position": "relative", "zIndex": 1}
            ),
            html.Div(
                "some text to display",
                style={
                    "position": "absolute",
                    "top": "200px",
                    "left": "250px",
                    "backgroundColor": "pink",
                    "padding": "10px",
                    "border": "1px solid black",
                    "borderRadius": "12px",
                    "zIndex": 2,
                    "boxShadow": "2px 2px 6px rgba(0,0,0,0.2)",
                    "fontWeight": "bold"
                }
            ),
        ],
        style={"position": "relative"}
    )
])

if __name__ == '__main__':
    app.run(debug=True)

But then you have the problem that, when download the plot, the annotation is no there. HTML elements like html.Div used as annotations in Dash cannot be captured in the image when using Plotly’s built-in download features. Another problem is the position of the annotation as html.Div.

Maybe someone with more knowledge can help you more, but I think is not possible from the fig.add_annotation.

2 Likes

Hey @David22, welcome back!

I don´t think so. If you want to maintain the interactivity (for annotations relative to the axes) I think the easiest way to to this is creating a function based on a closedShape which generates a rectangle with rounded edges.

2 Likes