aboutsummaryrefslogtreecommitdiffhomepage
path: root/services/nuldoc/public/slides/slide.js
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-02 03:28:57 +0900
committernsfisis <nsfisis@gmail.com>2026-08-02 03:29:01 +0900
commit12bc1c4123fa1227715d2c7dc8254bb8bd449fd8 (patch)
tree50dd9a58bd621557c6e6407cbc36956e0e6e7736 /services/nuldoc/public/slides/slide.js
parenta3d1c3bb7469a7a2d31de936be682d5bd4d38793 (diff)
downloadnsfisis.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.js63
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);