PDF zoom: use CSS zoom instead of re-render, abort stale renders
- Add render generation counter (_pdfRenderGen) to abort overlapping renders - Wrap all pages in #pdf-viewport div; zoom slider just updates style.zoom - Use 'input' event on zoom slider for live preview without re-rendering - enterPdfPaginatedMode resets viewport zoom to 1; exitPdfPaginatedMode restores it - Remove pdfZoom factor from renderPdf scale (CSS zoom handles it now) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
1cba67b3ed
commit
1026ed09a7
2 changed files with 26 additions and 4 deletions
|
|
@ -1637,6 +1637,9 @@ body.dnd-mode .timer-display {
|
||||||
}
|
}
|
||||||
.reader-settings-panel input[type="range"] { width:80px; }
|
.reader-settings-panel input[type="range"] { width:80px; }
|
||||||
|
|
||||||
|
/* PDF viewport wrapper — CSS zoom applied here for smooth zoom without re-render */
|
||||||
|
#pdf-viewport { transform-origin: top left; }
|
||||||
|
|
||||||
/* PDF inner container — shares origin with canvas so text layer aligns exactly */
|
/* PDF inner container — shares origin with canvas so text layer aligns exactly */
|
||||||
.pdf-page-inner { position:relative; display:inline-block; line-height:0; }
|
.pdf-page-inner { position:relative; display:inline-block; line-height:0; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2594,6 +2594,7 @@ let readerSearchOpen = false;
|
||||||
let pdfCurrentPage = 1;
|
let pdfCurrentPage = 1;
|
||||||
let pdfTotalPages = 0;
|
let pdfTotalPages = 0;
|
||||||
let _pdfPageTextBoxCache = {};
|
let _pdfPageTextBoxCache = {};
|
||||||
|
let _pdfRenderGen = 0;
|
||||||
let _touchStartX = 0;
|
let _touchStartX = 0;
|
||||||
|
|
||||||
if (typeof pdfjsLib !== 'undefined') {
|
if (typeof pdfjsLib !== 'undefined') {
|
||||||
|
|
@ -2836,7 +2837,9 @@ async function _parsePdfOutline(pdf, items, depth) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function renderPdf(arrayBuffer, contentEl, scaleOverride) {
|
async function renderPdf(arrayBuffer, contentEl, scaleOverride) {
|
||||||
|
const myGen = ++_pdfRenderGen;
|
||||||
const pdf = currentPdfDoc || await pdfjsLib.getDocument({data: new Uint8Array(arrayBuffer.slice(0))}).promise;
|
const pdf = currentPdfDoc || await pdfjsLib.getDocument({data: new Uint8Array(arrayBuffer.slice(0))}).promise;
|
||||||
|
if (_pdfRenderGen !== myGen) return null;
|
||||||
currentPdfDoc = pdf;
|
currentPdfDoc = pdf;
|
||||||
|
|
||||||
let pdfTitle = '', pdfAuthor = '';
|
let pdfTitle = '', pdfAuthor = '';
|
||||||
|
|
@ -2854,13 +2857,20 @@ async function renderPdf(arrayBuffer, contentEl, scaleOverride) {
|
||||||
|
|
||||||
contentEl.innerHTML = '';
|
contentEl.innerHTML = '';
|
||||||
|
|
||||||
|
// Viewport wrapper: CSS zoom controls display scale without re-rendering
|
||||||
|
const pdfVp = document.createElement('div');
|
||||||
|
pdfVp.id = 'pdf-viewport';
|
||||||
|
if (scaleOverride == null) pdfVp.style.zoom = readerSettings.pdfZoom / 100;
|
||||||
|
contentEl.appendChild(pdfVp);
|
||||||
|
|
||||||
const containerWidth = Math.min(contentEl.clientWidth - 32, 900);
|
const containerWidth = Math.min(contentEl.clientWidth - 32, 900);
|
||||||
|
|
||||||
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
|
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
|
||||||
|
if (_pdfRenderGen !== myGen) { contentEl.innerHTML = ''; return null; }
|
||||||
const page = await pdf.getPage(pageNum);
|
const page = await pdf.getPage(pageNum);
|
||||||
const naturalVp = page.getViewport({scale: 1});
|
const naturalVp = page.getViewport({scale: 1});
|
||||||
const scale = scaleOverride != null ? scaleOverride
|
const scale = scaleOverride != null ? scaleOverride
|
||||||
: Math.max(0.5, (containerWidth / naturalVp.width) * (readerSettings.pdfZoom / 100));
|
: Math.max(0.5, containerWidth / naturalVp.width);
|
||||||
const viewport = page.getViewport({scale});
|
const viewport = page.getViewport({scale});
|
||||||
|
|
||||||
const wrapper = document.createElement('div');
|
const wrapper = document.createElement('div');
|
||||||
|
|
@ -2878,7 +2888,7 @@ async function renderPdf(arrayBuffer, contentEl, scaleOverride) {
|
||||||
canvas.height = viewport.height;
|
canvas.height = viewport.height;
|
||||||
inner.appendChild(canvas);
|
inner.appendChild(canvas);
|
||||||
wrapper.appendChild(inner);
|
wrapper.appendChild(inner);
|
||||||
contentEl.appendChild(wrapper);
|
pdfVp.appendChild(wrapper);
|
||||||
|
|
||||||
await page.render({canvasContext: canvas.getContext('2d'), viewport}).promise;
|
await page.render({canvasContext: canvas.getContext('2d'), viewport}).promise;
|
||||||
|
|
||||||
|
|
@ -3424,11 +3434,16 @@ function toggleSettingsPanel() {
|
||||||
} else {
|
} else {
|
||||||
const zoomRange = panel.querySelector('#rs-zoom');
|
const zoomRange = panel.querySelector('#rs-zoom');
|
||||||
const zoomVal = panel.querySelector('#rs-zoom-val');
|
const zoomVal = panel.querySelector('#rs-zoom-val');
|
||||||
zoomRange.addEventListener('change', () => {
|
zoomRange.addEventListener('input', () => {
|
||||||
readerSettings.pdfZoom = parseInt(zoomRange.value, 10);
|
readerSettings.pdfZoom = parseInt(zoomRange.value, 10);
|
||||||
zoomVal.textContent = readerSettings.pdfZoom + '%';
|
zoomVal.textContent = readerSettings.pdfZoom + '%';
|
||||||
saveReaderSettings();
|
saveReaderSettings();
|
||||||
reRenderPdf();
|
if (readerSettings.pdfPaginated) {
|
||||||
|
pdfSmartZoomPage(pdfCurrentPage);
|
||||||
|
} else {
|
||||||
|
const vp = document.getElementById('pdf-viewport');
|
||||||
|
if (vp) vp.style.zoom = readerSettings.pdfZoom / 100;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
panel.querySelector('#rs-invert').addEventListener('click', function () {
|
panel.querySelector('#rs-invert').addEventListener('click', function () {
|
||||||
|
|
@ -3469,6 +3484,8 @@ function enterPdfPaginatedMode() {
|
||||||
if (!contentEl) return;
|
if (!contentEl) return;
|
||||||
contentEl.classList.add('pdf-paginated');
|
contentEl.classList.add('pdf-paginated');
|
||||||
contentEl.style.overflow = 'hidden';
|
contentEl.style.overflow = 'hidden';
|
||||||
|
const pdfVp = document.getElementById('pdf-viewport');
|
||||||
|
if (pdfVp) pdfVp.style.zoom = 1;
|
||||||
|
|
||||||
const wrappers = contentEl.querySelectorAll('.pdf-page-wrapper');
|
const wrappers = contentEl.querySelectorAll('.pdf-page-wrapper');
|
||||||
wrappers.forEach((w, i) => {
|
wrappers.forEach((w, i) => {
|
||||||
|
|
@ -3493,6 +3510,8 @@ function exitPdfPaginatedMode() {
|
||||||
const canvas = w.querySelector('canvas');
|
const canvas = w.querySelector('canvas');
|
||||||
if (canvas) canvas.style.transform = '';
|
if (canvas) canvas.style.transform = '';
|
||||||
});
|
});
|
||||||
|
const pdfVp = document.getElementById('pdf-viewport');
|
||||||
|
if (pdfVp) pdfVp.style.zoom = readerSettings.pdfZoom / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _pdfPaginatedClick(e) {
|
function _pdfPaginatedClick(e) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue