plotly / plotly.py

The interactive graphing library for Python :sparkles: This project now includes Plotly Express!
https://plotly.com/python/
MIT License
16.3k stars 2.55k forks source link

Allow drag zoom of arbitrary aspect ratio with `dcc.Graph` and image as data #4861

Open matt-sd-watson opened 5 days ago

matt-sd-watson commented 5 days ago

Our application uses dcc.Graph to render images. Currently, the zoom feature maintains the aspect ratio of the full-resolution image. Is it possible to configure the graph component to permit drag zooming of arbitrary aspect ratios? One consideration is that the behaviour would be separate from scollZoom as scrolling would have to maintain the current aspect ratio

alexcjohnson commented 5 days ago

Arbitrary aspect zoom normally is possible, unless your graph locks its aspect ratio, for example with yaxis.scaleanchor = “x”. Where this gets confusing is with image traces, that make this the default behavior. In that case you have to explicitly unlock it, for example: fig.update_layout(yaxis_scaleanchor=None)

matt-sd-watson commented 5 days ago

fig.update_layout(yaxis_scaleanchor=None) doesn't appear to work when the underlying data comes from px.imshow:

canvas = px.imshow(Image.fromarray(image.astype(np.uint8))
fig = go.Figure(canvas)
fig.update_layout(yaxis_scaleanchor=None)

the fig is then passed to the component:

dcc.Graph(config={"modeBarButtonsToAdd": [
        "drawclosedpath",
        "drawrect",
        "eraseshape"],
        'toImageButtonOptions': {'format': 'png', 'filename': filename, 'scale': 1},
        'edits': {'shapePosition': False}, 'scrollZoom': fullscreen_mode, 'displaylogo': False},
        relayoutData={'autosize': True},
        id=input_id,
        style=style_canvas,
        figure={'layout': dict(yaxis_scaleanchor=None, xaxis_showgrid=False, yaxis_showgrid=False,
                               newshape=dict(line=dict(color="white")),
                               xaxis=go.XAxis(showticklabels=False),
                               yaxis=go.YAxis(showticklabels=False),
                               margin=default_canvas_margins()
                               )})

using dash 2.10.2

alexcjohnson commented 5 days ago

Ah so it's False, not None... and it seems like in different situations the scaleanchor can get set on either x or y, so the most reliable way to do this I think is:

fig.update_layout(xaxis_scaleanchor=False, yaxis_scaleanchor=False)

or if you have multiple subplots:

fig.update_xaxes(scaleanchor=False).update_yaxes(scaleanchor=False)