- Self-contained Svelte component for embedding into a larger app.
- Performance-first: lazy render, caching, minimal DOM churn.
- Predictable UX: centered pages, fit-to-width on load, smooth zoom.
cd frontendnpm installnpm run buildcd ..python backend/app.py
<script>
import PdfViewer from "./lib/PdfViewer.svelte";
const overlays = [
{ id: "a1", page: 1, x: 72, y: 72, width: 200, height: 60, color: "#ff7a00" },
];
</script>
<PdfViewer
src="/docs/sample.pdf"
pageNumber={1}
pageMode="all"
renderText={true}
overlays={overlays}
scrollToAnnotationId={"a1"}
/>src(string, required)- PDF URL or file path.
pageNumber(number, 1-based)- Scrolls to this page when set.
pageMode("all" | "subset")"all": render all pages lazily."subset": render only the pages inpages.
pages(number[])- Used only when
pageMode="subset". - Invalid or missing page numbers are ignored.
- Used only when
renderText(boolean)- Enables pdf.js text layer for selection and CTRL+C.
overlays(array)- Bounding boxes drawn over pages.
scrollToAnnotationId(string | number | null)- Scrolls to the overlay with matching
idand centers it. - If the target page is not in the subset, it logs a warning and does nothing.
- Scrolls to the overlay with matching
scrollToAnnotationZoom(boolean)- When true, zooms in (if needed) so the target overlay fits comfortably in view.
debugScroll(boolean)- When true, logs scroll math to the PyWebView log file (see Debugging).
- Fit-to-width is computed on load using the first page and container width.
Ctrl+Wheelzooms smoothly via CSS preview, then re-renders at the new scale.- Zoom is cursor-anchored when the cursor is within the viewport.
- Pages are centered in the viewport.
- Lazy rendering uses
IntersectionObserverwith a large root margin.
- Coordinate system: PDF units with origin at bottom-left of the page.
- Required fields:
page,x,y,width,height. - Optional fields:
id,color,borderWidth,borderStyle,fill.
Overlay shape example:
{
id: "case-41",
page: 12,
x: 144,
y: 200,
width: 120,
height: 24,
color: "rgba(255, 0, 0, 0.8)",
borderWidth: 2,
borderStyle: "solid",
fill: "transparent"
}debugScrollwrites JSON lines tologs/scroll-debug.jsonlvia the PyWebView JS API.- Enable it only when troubleshooting scroll/zoom behavior.
PdfViewer.svelteorchestrates loading, paging, zoom, and rendering.FrameLayout.svelteprovides the centered layout shell.ScrollViewport.sveltehandles scroll and wheel events.PageStack.sveltescales gaps/padding viaviewScale.pdfjs.jswrapspdfjs-distand exposes render helpers.