fix: incremental PDF page rendering for exam setup backdrop
app-ci-deploy / test-build-deploy (push) Has been cancelled
app-ci-deploy / test-build-deploy (push) Has been cancelled
Rendering a 36-page AQA exam PDF sequentially created 36 large canvas elements, causing memory pressure and keeping pdfStatus='loading' for 60–120s in headless Chrome. Two changes: 1. pdfLoader.ts: reuse a single canvas (reduces peak memory from ~120MB to ~4MB) and fire onPageReady callback after each page so callers can stream pages to the canvas as they render. 2. ExamTemplateSetupPage.tsx: use the callback to add each PDF page shape to the tldraw canvas the moment it renders, making the first page visible within a few seconds rather than after all pages load. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
2de3e29179
commit
8e8a345e61
@@ -12,20 +12,27 @@ export interface PdfPageImage {
|
||||
height: number
|
||||
}
|
||||
|
||||
export async function loadPdfPageImages(pdfBytes: ArrayBuffer, targetWidth = PAGE_WIDTH): Promise<PdfPageImage[]> {
|
||||
export async function loadPdfPageImages(
|
||||
pdfBytes: ArrayBuffer,
|
||||
targetWidth = PAGE_WIDTH,
|
||||
onPageReady?: (pages: PdfPageImage[]) => void,
|
||||
): Promise<PdfPageImage[]> {
|
||||
const pdf = await pdfjsLib.getDocument({ data: new Uint8Array(pdfBytes) }).promise
|
||||
const pages: PdfPageImage[] = []
|
||||
// Reuse a single canvas across all pages to avoid allocating ~120 MB of canvas memory
|
||||
// for a typical 36-page exam paper.
|
||||
const canvas = document.createElement("canvas")
|
||||
|
||||
for (let pageNumber = 1; pageNumber <= pdf.numPages; pageNumber += 1) {
|
||||
const page = await pdf.getPage(pageNumber)
|
||||
const baseViewport = page.getViewport({ scale: 1 })
|
||||
const scale = targetWidth / baseViewport.width
|
||||
const viewport = page.getViewport({ scale })
|
||||
const canvas = document.createElement("canvas")
|
||||
canvas.width = Math.ceil(viewport.width)
|
||||
canvas.height = Math.ceil(viewport.height)
|
||||
const context = canvas.getContext("2d")
|
||||
if (!context) throw new Error("Unable to create PDF render canvas")
|
||||
context.clearRect(0, 0, canvas.width, canvas.height)
|
||||
await page.render({ canvasContext: context, viewport }).promise
|
||||
pages.push({
|
||||
pageNumber,
|
||||
@@ -33,6 +40,7 @@ export async function loadPdfPageImages(pdfBytes: ArrayBuffer, targetWidth = PAG
|
||||
width: canvas.width,
|
||||
height: canvas.height,
|
||||
})
|
||||
onPageReady?.([...pages])
|
||||
}
|
||||
|
||||
return pages
|
||||
|
||||
Reference in New Issue
Block a user