Learning in public — this reference is being written in the open. Unfinished pages are excluded from search engines.
paged.IDML Reference
SDK

Camera & navigation

Drive the SDK viewer's camera — zoom, scroll, fit, page navigation, and layout mode — with a live playground that calls each method as you click.

Tier: IntermediateIntermediateIIhow-to

The viewer is a camera over a laid-out document; you move the camera.

In short after await viewer.load(bytes) you drive the view with a small, imperative API — fit, setZoom/zoomIn/zoomOut, scrollTo/scrollBy, goToPage, and layoutMode. Zoom is clamped to [minZoom, maxZoom]; scroll is clamped to the content extent. The playground below renders a real two-page document — every button calls the method named in its tooltip, and the panel on the right logs the viewer's events as they fire.

Try it

100%
Booting the WebGPU viewer…
viewer.on(…)
Drive the viewer →
events appear here.

The toolbar maps one-to-one to the API: Fit page/widthviewer.fit(…), −/+viewer.zoomOut()/zoomIn(), ◀/▶viewer.goToPage(…), and layoutviewer.layoutMode(…). Watch the viewer.on(…) panel: driving the camera emits zoomChanged, pageChanged, and friends — the same events your app subscribes to.

In code

const viewer = await createViewer({ canvas });
await viewer.load(bytes);

viewer.fit('width');             // fit the page width to the viewport
viewer.setZoom(1.5, { anchor }); // zoom about a point so it stays put
viewer.goToPage(1);              // jump to the second page
viewer.layoutMode('continuous'); // switch to a continuous scroll of pages

For custom navigation UIs — a page rail, a minimap, a fit-to-selection button — the SDK also exports the pure camera math (fitPage, zoomAt, scrollToPage, clampZoom, clampScroll, contentExtent, currentPageAt) so you can compute transforms without a viewer instance.

The camera API

MemberSignatureDescription
Viewer.zoomreadonly zoom: numberThe current zoom factor (1 = 100%).
Viewer.setZoomsetZoom(zoom: number, opts?: { anchor?: { x: number; y: number } }): voidSet the zoom factor, optionally anchored about a viewport point so that point stays put.
Viewer.zoomInzoomIn(): voidStep zoom up by one notch (toward maxZoom).
Viewer.zoomOutzoomOut(): voidStep zoom down by one notch (toward minZoom).
Viewer.minZoomreadonly minZoom: numberThe smallest allowed zoom factor.
Viewer.maxZoomreadonly maxZoom: numberThe largest allowed zoom factor.
Viewer.fitfit(mode: 'page' | 'width'): voidFit the current page to the viewport — whole page, or page width.
Viewer.scrollreadonly scroll: { x: number; y: number }The current scroll offset, in CSS pixels.
Viewer.scrollToscrollTo(x: number, y: number): voidScroll to an absolute offset (clamped to the content extent).
Viewer.scrollByscrollBy(dx: number, dy: number): voidScroll by a relative delta.
MemberSignatureDescription
Viewer.pageCountreadonly pageCount: numberNumber of pages in the loaded document.
Viewer.currentPagereadonly currentPage: numberThe zero-based index of the page currently in view.
Viewer.goToPagegoToPage(index: number): voidScroll the given page into view and make it current. Emits `pageChanged`.
Viewer.layoutModelayoutMode(mode?: LayoutMode): LayoutModeGet or set the layout mode — 'single' (one page) or 'continuous' (a scroll of stacked pages).

Camera helpers

MemberSignatureDescription
clampZoomclampZoom(zoom: number, limits: ZoomLimits): numberClamp a zoom factor into [min, max].
clampScrollclampScroll(x: number, y: number, viewport: Viewport, extent: ContentExtent): { x: number; y: number }Clamp a scroll offset to the content extent for a viewport.
contentExtentcontentExtent(layout: SessionPagesLayout, zoom: number): ContentExtentTotal scrollable content size at a given zoom.
currentPageAtcurrentPageAt(layout: SessionPagesLayout, scrollY: number): numberWhich page is in view at a scroll position (continuous mode).
fitPagefitPage(page: SessionPageRect, viewport: Viewport, mode: 'page' | 'width'): numberThe zoom that fits a page to the viewport.
scrollToPagescrollToPage(layout: SessionPagesLayout, pageIndex: number, viewport: Viewport): numberThe scrollY that brings a page into view.
zoomAtzoomAt(point, newZoom, currentZoom, scroll): { x: number; y: number }The scroll offset that keeps a point fixed while zooming about it.

Frequently asked questions

Why are my zoom calls being ignored at the extremes? Zoom is clamped to [minZoom, maxZoom]. Read those properties to bound your own UI, or use clampZoom(z, { min, max }).

How do I keep a point fixed while zooming (zoom-to-cursor)? Pass an anchor to setZoom, or compute the resulting scroll yourself with zoomAt(point, newZoom, currentZoom, scroll).

What is the difference between single and continuous layout? single shows one page at a time; continuous stacks all pages in a scroll. Set it at creation via CreateViewerOptions.layoutMode or at runtime with viewer.layoutMode('continuous').

On this page