Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
In this article, you learn how to optimize resize handling in Power BI custom visuals that you build with powerbi-visuals-api. When a report user changes a custom visual's size, Power BI calls the visual's update() method with VisualUpdateOptions, including the current viewport dimensions. This guidance applies only to Power BI custom visuals; it doesn't change resize behavior for built-in Power BI visuals.
If a custom visual treats every VisualUpdateType.Resize event as a full data change, repeated resize events can reprocess options.dataViews, rebuild Document Object Model (DOM) elements, and block the browser main thread. To keep resize interactions responsive, use VisualUpdateType bit flags to separate data changes from viewport changes, cache processed visual state, and defer layout-dependent rendering until VisualUpdateType.ResizeEnd.
How do Power BI VisualUpdateType resize events work?
The Visual.update(options) method receives an options.type field indicating why Power BI triggered the update. The viewport is the current custom visual container size from options.viewport, including width and height.
| VisualUpdateType flag | When Power BI sends it | Resize handling |
|---|---|---|
VisualUpdateType.Data |
Data or data view changed. | Perform a full render. |
VisualUpdateType.Resize |
A Power BI custom visual is being resized, and Power BI sends repeated events while the resize is in progress. | Do only minimal viewport work. |
VisualUpdateType.ResizeEnd |
The resize operation completed. | Recalculate final layout-dependent elements only when needed. |
VisualUpdateType.ViewMode |
View mode changed, such as from edit mode to view mode. | Perform a full render. |
VisualUpdateType.Style |
Theme or style changed. | Perform a full render. |
Key insight: VisualUpdateType is a bit-flag enum. A single options.type value can include VisualUpdateType.Resize and other update reasons, such as VisualUpdateType.Data or VisualUpdateType.Style. Use bitwise checks, such as (options.type & VisualUpdateType.Resize) !== 0, instead of equality checks. During VisualUpdateType.Resize, do only minimal viewport work. During VisualUpdateType.ResizeEnd, perform final layout recalculations that require the final container size.
How do I implement a resize-only update pattern?
The resize-update pattern separates resize-only work from updates that require data, style, or view-mode rendering. If options.type includes any non-resize flags, perform a full render instead of treating the update as a viewport-only change.
| VisualUpdateType condition | Rendering behavior | Work to perform |
|---|---|---|
| Non-resize flags are present | Full render | Reprocess data, apply style or view-mode changes, and rebuild elements that depend on those changes. |
Only VisualUpdateType.Resize is present |
Resize-only rendering | Adjust viewport dimensions or scale existing content without reprocessing data. |
VisualUpdateType.ResizeEnd is present with only resize flags |
Resize-end rendering | Recalculate final layout-dependent elements after the container reaches its final size. |
public update(options: VisualUpdateOptions): void {
const resizeFlags = VisualUpdateType.Resize | VisualUpdateType.ResizeEnd;
const isResize = (options.type & VisualUpdateType.Resize) !== 0;
const isResizeEnd = (options.type & VisualUpdateType.ResizeEnd) !== 0;
const hasOnlyResizeFlags = (options.type & ~resizeFlags) === 0;
if (!hasOnlyResizeFlags) {
this.fullRender(options);
return;
}
if (isResizeEnd) {
// Resize finished; recalculate layout-dependent elements only when needed.
this.recalculateLayout(options.viewport);
return;
}
if (isResize) {
// Adjust only layout and viewport; do not reprocess data or rebuild the DOM.
this.adjustViewport(options.viewport);
return;
}
// Full render for data changes, style changes, and other updates.
this.fullRender(options);
}
After you add the pattern, verify it by resizing the custom visual on a report canvas. The visual should update size during the drag without reprocessing the data view, and final layout-dependent elements, such as axis labels, should appear in their final positions after VisualUpdateType.ResizeEnd.
What work belongs in resize and resize-end events?
During an active VisualUpdateType.Resize event, prefer operations that update the viewport or scale existing rendered elements. Save resource-intensive work for VisualUpdateType.ResizeEnd or for updates that include data, style, or view-mode changes.
Work to do during VisualUpdateType.Resize
- Update SVG
viewBoxor container dimensions with CSS. - Scale existing rendered content, for example, with CSS
transform. - Store the new
options.viewportwidth and height for later use.
Work to avoid during VisualUpdateType.Resize
- Requery or reprocess
options.dataViews. - Rebuild DOM elements, such as axes, legends, or data points.
- Recalculate text measurements for all labels.
- Trigger resource-intensive layout algorithms, such as force-directed graphs or treemaps.
Work to do on VisualUpdateType.ResizeEnd
- Recalculate axis tick counts or text labels that depend on final
options.viewportdimensions. - Rerender elements that can't scale proportionally.
- Persist final viewport-dependent state if the visual stores layout metadata.
Which resize-resilient rendering techniques should I use?
Use these techniques to reduce the amount of JavaScript work that each resize event performs. Choose the approach that matches how the visual renders axes, labels, legends, and data marks.
| Resize technique | Use this technique when | Resize benefit |
|---|---|---|
SVG viewBox |
The visual content can scale proportionally. | Set a fixed viewBox with preserveAspectRatio and let the browser scale automatically, so update() doesn't need resize-specific work. |
| CSS-driven layout | Containers, legends, or simple marks can respond to CSS sizing. | Use percentage-based widths and heights or flexbox so the browser handles resize without JavaScript intervention. |
| Debounced recalculations | The visual must recompute layout after the final container size is known. | Debounce recalculation on VisualUpdateType.ResizeEnd to avoid redundant work from rapid successive resizes. |
| Cached processed data | Data processing doesn't depend on viewport dimensions. | Store processed data points so VisualUpdateType.Resize and VisualUpdateType.ResizeEnd render with cached data and the new viewport dimensions. |
What performance impact does resize optimization have?
Power BI custom visuals that perform full renders on every VisualUpdateType.Resize call can make resizing feel slow, create unnecessary DOM changes, and block the browser main thread across the report page. A resize-optimized custom visual skips data processing during active resize, updates only viewport-dependent presentation, and performs final layout calculation on VisualUpdateType.ResizeEnd.
How do I verify resize optimization?
Use this checklist to confirm that resize behavior uses minimal resources while preserving full rendering for non-resize updates.
- Check
options.typein yourupdate()method. - Use bitwise checks for
VisualUpdateTypeflags. - Return early or do minimal work when
options.typeincludesVisualUpdateType.Resize. - Defer resource-intensive recalculations to
VisualUpdateType.ResizeEnd. - Use CSS/SVG responsive techniques where possible.
- Cache processed data between updates.
- Verify that data processing doesn't run during active resize events.
Where can I find Power BI custom visual resize resources?
Use these resources for the API details and related performance guidance: