diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-08-02 03:28:57 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-08-02 03:29:01 +0900 |
| commit | 12bc1c4123fa1227715d2c7dc8254bb8bd449fd8 (patch) | |
| tree | 50dd9a58bd621557c6e6407cbc36956e0e6e7736 /services/nuldoc/public/slides/slide.js | |
| parent | a3d1c3bb7469a7a2d31de936be682d5bd4d38793 (diff) | |
| download | nsfisis.dev-12bc1c4123fa1227715d2c7dc8254bb8bd449fd8.tar.gz nsfisis.dev-12bc1c4123fa1227715d2c7dc8254bb8bd449fd8.tar.zst nsfisis.dev-12bc1c4123fa1227715d2c7dc8254bb8bd449fd8.zip | |
fix(slides): fix flickering
Diffstat (limited to 'services/nuldoc/public/slides/slide.js')
| -rw-r--r-- | services/nuldoc/public/slides/slide.js | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/services/nuldoc/public/slides/slide.js b/services/nuldoc/public/slides/slide.js index 8d6ba52d..a90fda7a 100644 --- a/services/nuldoc/public/slides/slide.js +++ b/services/nuldoc/public/slides/slide.js @@ -8,13 +8,22 @@ async function init() { const url = canvas.dataset.slideLink; let pageNum = 1; - let pageNumPending = null; - let pageRendering = false; let doc = null; + let renderTask = null; + let renderToken = 0; + + const backCanvas = document.createElement("canvas"); + const backCtx = backCanvas.getContext("2d"); const renderPage = async (num) => { - pageRendering = true; + const token = ++renderToken; + if (renderTask !== null) { + renderTask.cancel(); + renderTask = null; + } + const page = await doc.getPage(num); + if (token !== renderToken) return; const baseViewport = page.getViewport({ scale: 1.0 }); const containerWidth = canvas.parentElement.clientWidth; @@ -22,65 +31,69 @@ async function init() { const viewport = page.getViewport({ scale }); const outputScale = globalThis.devicePixelRatio || 1; - canvas.height = Math.floor(viewport.height * outputScale); - canvas.width = Math.floor(viewport.width * outputScale); - canvas.style.width = Math.floor(viewport.width) + "px"; - canvas.style.height = Math.floor(viewport.height) + "px"; + const cssWidth = Math.floor(viewport.width); + const cssHeight = Math.floor(viewport.height); + backCanvas.width = Math.floor(viewport.width * outputScale); + backCanvas.height = Math.floor(viewport.height * outputScale); const transform = outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null; // TODO: error handling - await page.render({ - canvasContext: ctx, + const task = page.render({ + canvasContext: backCtx, viewport, transform, }); - - pageRendering = false; - if (pageNumPending !== null) { - renderPage(pageNumPending); - pageNumPending = null; + renderTask = task; + try { + await task.promise; + } catch (e) { + if (e?.name === "RenderingCancelledException") return; + throw e; + } finally { + if (renderTask === task) renderTask = null; } - }; + if (token !== renderToken) return; - const queueRenderPage = (num) => { - if (pageRendering) { - pageNumPending = num; - } else { - renderPage(num); + if (canvas.width !== backCanvas.width || canvas.height !== backCanvas.height) { + canvas.width = backCanvas.width; + canvas.height = backCanvas.height; + canvas.style.width = cssWidth + "px"; + canvas.style.height = cssHeight + "px"; } + ctx.drawImage(backCanvas, 0, 0); }; const prev = document.getElementById("prev"); prev.addEventListener("click", () => { if (pageNum <= 1) return; pageNum--; - queueRenderPage(pageNum); + renderPage(pageNum); }); const next = document.getElementById("next"); next.addEventListener("click", () => { if (pageNum >= doc.numPages) return; pageNum++; - queueRenderPage(pageNum); + renderPage(pageNum); }); document.addEventListener("keydown", (e) => { if (e.key === "ArrowLeft" || e.key === "h") { if (pageNum <= 1) return; pageNum--; - queueRenderPage(pageNum); + renderPage(pageNum); } else if (e.key === "ArrowRight" || e.key === "l") { if (pageNum >= doc.numPages) return; pageNum++; - queueRenderPage(pageNum); + renderPage(pageNum); } }); // TODO: error handling doc = await getDocument(url).promise; - queueRenderPage(pageNum); + renderPage(pageNum); } document.addEventListener("DOMContentLoaded", init); |
