Render persistent manual plot layout edits across re-renders
Source:R/plot_helpers.R
finalize_manual_edits.RdRender-step companion to setup_manual_edits(). Call this inside
your module's plotly::renderPlotly() on the freshly rebuilt
figure, as the last step: return what it returns.
Usage
finalize_manual_edits(
fig,
plot_source,
store,
session,
regen_keys = character(0)
)Arguments
- fig
A plotly figure object, typically the result of your plotting pipeline. If
NULL, it is returned unchanged.- plot_source
Character scalar. The same plotly event source id passed to
setup_manual_edits(); assigned tofig$x$source.- store
The list returned by
setup_manual_edits().- session
The module's
sessionobject, used to namespace the colorbar drag input.- regen_keys
Character vector of annotation keys (e.g.
"axis:y") whosetextis regenerated on every rebuild and must not be overwritten by a captured edit. Pass the axis side(s) carrying an active data adjustment so the freshly built label (e.g."log2(units)") always wins, while the captured position still persists. Defaults to none (all captured props are restored, the pre-existing behaviour).
Value
The finalized plotly figure, ready to be returned from
plotly::renderPlotly(). Inside a render, when only the layout changed,
it instead sends the layout and cancels the render.
Details
It performs six jobs:
tags the figure with the module's plotly event
sourceso itsplotly_relayoutevents are captured bysetup_manual_edits();restores any manually repositioned legend, annotations, axis titles, and colorbar captured so far;
records the figure so future relayout events can be matched to stable annotation keys (surviving re-ordering on rebuild);
attaches the JavaScript listener that forwards colorbar drags;
has the figure re-rendered in place:
layout.transition = TRUEmakes the plotly widget update its graph withPlotly.react()instead of purging and recreating it, which is faster and keeps the user's zoom and toggled legend entries wheneverlayout.uirevisionis unchanged (the cached modules set it per build of the plot, so styling changes keep the view). A small script clears the previous render's event listeners first, which purging used to; andsends only the layout when nothing else changed: if the figure's traces, config,
layout.uirevision, and everything else but its layout match the figure last sent to this output, the new layout goes to the browser in a small message, applied withPlotly.react()over the traces already drawn, and the render is cancelled (req(FALSE, cancelOutput = TRUE)), so no code after this call runs. A styling change then costs kilobytes rather than the whole figure. Setoptions(VizModules.layout.updates = FALSE)to always send the whole figure.
Restored edits are applied under shiny::isolate() so re-applying
them never triggers an additional re-render.
See also
setup_manual_edits() for the setup-step companion.