rc-virtual-canvas
Scrollable virtual canvas for rendering large coordinate-space content.
Overlays a transparent scrollable div on top of a slotted <canvas> element,
dispatching rc-virtual-canvas-render events with the current viewport and
content rectangles. Consumers draw only what is visible.
- Package
@rcarls/rc-virtual-canvas- Element
<rc-virtual-canvas>- Native dependency
- Requires a direct child native canvas
- State model
- Virtual scroll geometry
- Main events
rc-virtual-canvas-pointerrc-virtual-canvas-render- Related
- Usage rulesTheme previews
Installation
- npm
- Yarn
- pnpm
npm install @rcarls/rc-webcomponents@next
yarn add @rcarls/rc-webcomponents@next
pnpm add @rcarls/rc-webcomponents@next
import '@rcarls/rc-webcomponents/rc-virtual-canvas/define';
Usage
Place a <canvas> inside the component, set content-width and content-height to the size of
the whole virtual surface, and draw the visible part on each rc-virtual-canvas-render event.
<rc-virtual-canvas content-width="4000" content-height="3000" style="width: 800px; height: 600px">
<canvas aria-label="Floor plan" width="800" height="600"></canvas>
</rc-virtual-canvas>
Live demo
The native <canvas> must be a direct child of rc-virtual-canvas. Keeping it in light DOM
preserves the consumer's drawing surface and accessible fallback content before and after the
custom element upgrades.
Accessibility
A canvas is a bitmap with no semantics of its own, so the component adds none. When the drawing carries information or interaction:
- Name the
<canvas>witharia-labeloraria-labelledby. - Provide the same information outside the canvas, such as in a table, hidden visually rather
than with
display: none. - Give interactive content, such as hit-testing or dragging, keyboard equivalents on a separate focusable element.
Theming
The default demo mode shows the component without a package theme. Use the shared preview controls on this page to compare inherited, light, and dark color schemes or to apply the optional Material theme only inside the demo frames.
API
Properties
| Property | Markup | Type | Default | Description |
|---|---|---|---|---|
contentWidth | content-width | Unknown | Not specified | Pixel width of the virtual content |
contentHeight | content-height | Unknown | Not specified | Pixel height of the virtual content |
autoResizeCanvas | auto-resize-canvas | boolean | true | When true, keep the slotted canvas backing store aligned to the viewport. |
renderMode | render-mode | RCVirtualCanvasRenderMode | 'continuous' | Controls when render events are dispatched. |
imageRendering | image-rendering | RCVirtualCanvasImageRendering | 'auto' | Convenience image-rendering value applied to the slotted canvas. |
canvasScaleX | JS property only | number | Not specified | Ratio of canvas backing-store pixels to CSS pixels along the x-axis. Use as the x-scale factor in `ctx.scale()` to draw at CSS pixel resolution. When `autoResizeCanvas` is true, CSS zoom changes this ratio along with the backing-store resolution. |
canvasScaleY | JS property only | number | Not specified | Ratio of canvas backing-store pixels to CSS pixels along the y-axis. Use as the y-scale factor in `ctx.scale()` to draw at CSS pixel resolution. CSS zoom can make this ratio differ from `devicePixelRatio`. |
Methods
| Method | Description |
|---|---|
getViewRect() | Returns a frozen snapshot of the current viewport rectangle. Safe to keep between frames — the returned object will not be mutated by future scroll or resize work. |
scrollToContent(x: number, y: number, options: ScrollOptions) | Scrolls so the content coordinate is at the viewport origin. |
centerOnContent(x: number, y: number, options: ScrollOptions) | Scrolls so the content coordinate is centered in the viewport. |
clientToContent(clientX: number, clientY: number) | Converts browser client coordinates to CSS-pixel content coordinates. Canvas backing-store resolution does not change content coordinates. |
contentToClient(x: number, y: number) | Converts content coordinates back to browser client coordinates. |
requestRender(reason: RCVirtualCanvasRenderReason) | Queues a render event on the next animation frame. Required when `renderMode` is `'manual'`. In other modes the component schedules renders automatically; calling this with reason `'animation-frame'` is a no-op when `renderMode` is `'viewport-change'`. |
Events
| Event | Detail type | Description |
|---|---|---|
rc-virtual-canvas-pointer | CustomEvent | Fires pointer/mouse input mapped to virtual content coordinates. |
rc-virtual-canvas-render | CustomEvent | Fires with viewport data when the canvas should redraw. |
Slots
| Name | Description |
|---|---|
(default) | The HTMLCanvasElement |
overlay | Optional viewport-positioned content rendered inside the scroll container above the canvas. |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--rc-virtual-canvas-scrollbar-width | thin | `scrollbar-width` of the internal scroll container. |
--rc-virtual-canvas-scrollbar-size | auto | WebKit scrollbar thickness. |
--rc-virtual-canvas-scrollbar-thumb-background | ButtonFace | WebKit scrollbar thumb color. |
--rc-virtual-canvas-scrollbar-button-background | ButtonFace | WebKit scrollbar button color. |
--rc-virtual-canvas-scrollbar-track-background | Canvas | WebKit scrollbar track color. |
--rc-virtual-canvas-image-rendering | auto | `image-rendering` applied to the slotted canvas; kept in sync with the `imageRendering` property. |
CSS Parts
| Part | Description |
|---|---|
scroller | Internal scroll container that owns the virtual content scroll range. |
overlay | Viewport-positioned overlay container rendered inside the scroll container. |
Read-only properties
These are computed getters exposed for rendering convenience. They do not appear in the generated API table above.
| Property | Type | Description |
|---|---|---|
canvasScaleX | number | Ratio of backing-store pixels to local CSS pixels along the x-axis. CSS zoom can make it differ from devicePixelRatio. Use it to scale the drawing context to CSS pixel space. |
canvasScaleY | number | Ratio of canvas backing-store pixels to CSS pixels along the y-axis. |
Zoom and scale
rc-virtual-canvas is a pan-only viewport. It does not manage a content scale factor. Zoom (pinch-to-zoom, scroll-to-zoom) is the consumer's responsibility and should be applied by:
- Scaling the canvas context (
ctx.scale(zoom, zoom)) before drawing, and - Adjusting
contentWidthandcontentHeightto reflect the scaled content dimensions so the scrollable area matches.
CSS zoom on the component or an ancestor changes the canvas's rendered size and backing-store
resolution. clientToContent() and contentToClient() continue to use CSS-pixel content
coordinates; canvasScaleX and canvasScaleY report the backing-store pixels per local CSS pixel.