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.
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
The toolbar maps one-to-one to the API: Fit page/width → viewer.fit(…),
−/+ → viewer.zoomOut()/zoomIn(), ◀/▶ → viewer.goToPage(…), and
layout → viewer.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 pagesFor 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
| Member | Signature | Description |
|---|---|---|
| Viewer.zoom | readonly zoom: number | The current zoom factor (1 = 100%). |
| Viewer.setZoom | setZoom(zoom: number, opts?: { anchor?: { x: number; y: number } }): void | Set the zoom factor, optionally anchored about a viewport point so that point stays put. |
| Viewer.zoomIn | zoomIn(): void | Step zoom up by one notch (toward maxZoom). |
| Viewer.zoomOut | zoomOut(): void | Step zoom down by one notch (toward minZoom). |
| Viewer.minZoom | readonly minZoom: number | The smallest allowed zoom factor. |
| Viewer.maxZoom | readonly maxZoom: number | The largest allowed zoom factor. |
| Viewer.fit | fit(mode: 'page' | 'width'): void | Fit the current page to the viewport — whole page, or page width. |
| Viewer.scroll | readonly scroll: { x: number; y: number } | The current scroll offset, in CSS pixels. |
| Viewer.scrollTo | scrollTo(x: number, y: number): void | Scroll to an absolute offset (clamped to the content extent). |
| Viewer.scrollBy | scrollBy(dx: number, dy: number): void | Scroll by a relative delta. |
Page navigation & layout
| Member | Signature | Description |
|---|---|---|
| Viewer.pageCount | readonly pageCount: number | Number of pages in the loaded document. |
| Viewer.currentPage | readonly currentPage: number | The zero-based index of the page currently in view. |
| Viewer.goToPage | goToPage(index: number): void | Scroll the given page into view and make it current. Emits `pageChanged`. |
| Viewer.layoutMode | layoutMode(mode?: LayoutMode): LayoutMode | Get or set the layout mode — 'single' (one page) or 'continuous' (a scroll of stacked pages). |
Camera helpers
| Member | Signature | Description |
|---|---|---|
| clampZoom | clampZoom(zoom: number, limits: ZoomLimits): number | Clamp a zoom factor into [min, max]. |
| clampScroll | clampScroll(x: number, y: number, viewport: Viewport, extent: ContentExtent): { x: number; y: number } | Clamp a scroll offset to the content extent for a viewport. |
| contentExtent | contentExtent(layout: SessionPagesLayout, zoom: number): ContentExtent | Total scrollable content size at a given zoom. |
| currentPageAt | currentPageAt(layout: SessionPagesLayout, scrollY: number): number | Which page is in view at a scroll position (continuous mode). |
| fitPage | fitPage(page: SessionPageRect, viewport: Viewport, mode: 'page' | 'width'): number | The zoom that fits a page to the viewport. |
| scrollToPage | scrollToPage(layout: SessionPagesLayout, pageIndex: number, viewport: Viewport): number | The scrollY that brings a page into view. |
| zoomAt | zoomAt(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').