ViewManager API
The DOM and canvas coordination layer for Scrivr's rendering engine.
ViewManager is the component that bridges Editor (state + layout) with the browser DOM.
It manages the lifecycle of per-page <div> containers and <canvas> elements, implements
virtual scrolling, and orchestrates canvas painting.
You do not need to use ViewManager directly. The <Scrivr /> React component handles
ViewManager construction and teardown automatically. This page is for library contributors
and developers building custom rendering adapters.
Construction
import { ViewManager } from '@scrivr/core';
const vm = new ViewManager(editor, container, {
gap: 24, // px between pages. Default: 24
overscan: 500, // virtual scroll overscan px. Default: 500
});| Argument | Type | Description |
|---|---|---|
editor | Editor | The editor instance to render |
container | HTMLElement | DOM element to render pages into |
options.gap | number | Gap in px between page elements. Default: 24 |
options.overscan | number | Extra px around viewport to keep painted. Default: 500 |
options.showMarginGuides | boolean | Draw faint margin guide lines on each page. Default: false |
On construction, ViewManager:
- Subscribes to the editor via
editor.subscribe() - Calls
editor.setPageElementLookup()with a resolver that returns each page's DOM element - Creates the initial set of page DOM elements from
editor.layout - Begins watching page visibility with an
IntersectionObserver
What It Owns
| Resource | Description |
|---|---|
Per-page <div> wrappers | One per page in DocumentLayout, sized to pageConfig.pageWidth × pageConfig.pageHeight |
Content <canvas> | Draws text, images, and block backgrounds (one per page) |
Overlay <canvas> | Draws cursor, selection highlights, and extension overlays (one per page) |
IntersectionObserver | Watches page visibility; only paints pages in (or near) the viewport |
editor.subscribe cleanup fn | Unregisters on destroy() |
Virtual Scrolling
ViewManager implements virtual scrolling by painting only pages that are intersecting with the
viewport's overscan zone. Pages outside this zone are kept in the DOM (to preserve scroll position)
but their canvas content is cleared to free GPU memory.
The overscan value (default 500px) controls how far beyond the visible area pages are kept
actively painted. Increasing this reduces the chance of seeing blank pages during fast scrolling.
destroy()
vm.destroy(): voidFull cleanup:
- Unsubscribes from the editor
- Disconnects the
IntersectionObserver - Removes all page DOM elements from the container
Always call destroy() before discarding a ViewManager instance. The <Scrivr /> component
calls this in its useEffect cleanup.
<Scrivr /> as a Thin Wrapper
The full implementation of <Scrivr /> is:
useEffect(() => {
if (!editor || !containerRef.current) return;
editor.mount(containerRef.current);
const vm = new ViewManager(editor, containerRef.current, { gap, overscan });
return () => {
vm.destroy();
editor.unmount();
};
}, [editor, gap, overscan]);If you need custom behaviour (e.g. rendering into a Shadow DOM, or driving the canvas from
a non-React framework), copy this pattern and manage the ViewManager lifecycle yourself.