From e316d787556d2e6e8c04a314904e6e60e67a8218 Mon Sep 17 00:00:00 2001 From: Artur Adib Date: Wed, 30 Nov 2011 14:19:07 -0500 Subject: [PATCH] Smoother thumbnail scrolling via lazy rendering --- web/viewer.html | 4 +- web/viewer.js | 113 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 78 insertions(+), 39 deletions(-) diff --git a/web/viewer.html b/web/viewer.html index a72503eee..ebc0bcb06 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -28,7 +28,6 @@ - @@ -119,6 +118,7 @@
Loading... 0%
+ + - diff --git a/web/viewer.js b/web/viewer.js index bfb3a4303..e945dc434 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -13,19 +13,6 @@ var kMinScale = 0.25; var kMaxScale = 4.0; -var Cache = function cacheCache(size) { - var data = []; - this.push = function cachePush(view) { - var i = data.indexOf(view); - if (i >= 0) - data.splice(i); - data.push(view); - if (data.length > size) - data.shift().update(); - }; -}; - -var cache = new Cache(kCacheSize); var currentPageNumber = 1; var PDFView = { @@ -294,6 +281,7 @@ var PDFView = { outlineScrollView.setAttribute('hidden', 'true'); thumbsSwitchButton.setAttribute('data-selected', true); outlineSwitchButton.removeAttribute('data-selected'); + updateThumbViewArea(); break; case 'outline': thumbsScrollView.setAttribute('hidden', 'true'); @@ -328,6 +316,34 @@ var PDFView = { currentHeight += singlePage.height * singlePage.scale + kBottomMargin; } return visiblePages; + }, + + getVisibleThumbs: function pdfViewGetVisibleThumbs() { + var thumbs = this.thumbnails; + var kBottomMargin = 5; + var visibleThumbs = []; + + var view = document.getElementById('sidebarScrollView'); + var currentHeight = kBottomMargin; + var top = view.scrollTop; + for (var i = 1; i <= thumbs.length; ++i) { + var thumb = thumbs[i - 1]; + var thumbHeight = thumb.height * thumb.scaleY + kBottomMargin; + if (currentHeight + thumbHeight > top) + break; + + currentHeight += thumbHeight; + } + + var bottom = top + view.clientHeight; + for (; i <= thumbs.length && currentHeight < bottom; ++i) { + var singleThumb = thumbs[i - 1]; + visibleThumbs.push({ id: singleThumb.id, y: currentHeight, + view: singleThumb }); + currentHeight += singleThumb.height * singleThumb.scaleY + kBottomMargin; + } + + return visibleThumbs; } }; @@ -510,6 +526,19 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { PDFView.page = id; return false; }; + + var view = page.view; + this.width = view.width; + this.height = view.height; + this.id = id; + + var maxThumbSize = 134; + var canvasWidth = pageRatio >= 1 ? maxThumbSize : + maxThumbSize * pageRatio; + var canvasHeight = pageRatio <= 1 ? maxThumbSize : + maxThumbSize / pageRatio; + this.scaleX = (canvasWidth / this.width); + this.scaleY = (canvasHeight / this.height); var div = document.createElement('div'); div.id = 'thumbnailContainer' + id; @@ -526,11 +555,8 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { canvas.id = 'thumbnail' + id; canvas.mozOpaque = true; - var maxThumbSize = 134; - canvas.width = pageRatio >= 1 ? maxThumbSize : - maxThumbSize * pageRatio; - canvas.height = pageRatio <= 1 ? maxThumbSize : - maxThumbSize / pageRatio; + canvas.width = canvasWidth; + canvas.height = canvasHeight; div.setAttribute('data-loaded', true); div.appendChild(canvas); @@ -542,8 +568,8 @@ var ThumbnailView = function thumbnailView(container, page, id, pageRatio) { ctx.restore(); var view = page.view; - var scaleX = (canvas.width / page.width); - var scaleY = (canvas.height / page.height); + var scaleX = this.scaleX; + var scaleY = this.scaleY; ctx.translate(-view.x * scaleX, -view.y * scaleY); div.style.width = (view.width * scaleX) + 'px'; div.style.height = (view.height * scaleY) + 'px'; @@ -613,8 +639,7 @@ function updateViewarea() { var visiblePages = PDFView.getVisiblePages(); for (var i = 0; i < visiblePages.length; i++) { var page = visiblePages[i]; - if (PDFView.pages[page.id - 1].draw()) - cache.push(page.view); + PDFView.pages[page.id - 1].draw(); } if (!visiblePages.length) @@ -641,6 +666,35 @@ window.addEventListener('scroll', function webViewerScroll(evt) { updateViewarea(); }, true); + +var sidebarScrollView = document.getElementById('sidebarScrollView'); +var thumbnailTimer; + +function updateThumbViewArea() { + // Only render thumbs after pausing scrolling for this amount of time + // (makes UI more responsive) + var delay = 50; // in ms + + if (thumbnailTimer) + clearTimeout(thumbnailTimer); + + thumbnailTimer = setTimeout(function(){ + var visibleThumbs = PDFView.getVisibleThumbs(); + for (var i = 0; i < visibleThumbs.length; i++) { + var thumb = visibleThumbs[i]; + PDFView.thumbnails[thumb.id - 1].draw(); + } + }, delay); +} + +sidebarScrollView.addEventListener('scroll', function thumbViewScroll(evt) { + updateThumbViewArea(); +}, true); + +window.addEventListener('transitionend', function webViewerTransitionend(evt) { + updateThumbViewArea(); +}, true); + window.addEventListener('resize', function webViewerResize(evt) { if (document.getElementById('pageWidthOption').selected || document.getElementById('pageFitOption').selected) @@ -681,21 +735,6 @@ window.addEventListener('change', function webViewerChange(evt) { document.getElementById('download').setAttribute('hidden', 'true'); }, true); -window.addEventListener('transitionend', function webViewerTransitionend(evt) { - var pageIndex = 0; - var pagesCount = PDFView.pages.length; - - var container = document.getElementById('sidebarView'); - container._interval = window.setInterval(function interval() { - if (pageIndex >= pagesCount) { - window.clearInterval(container._interval); - return; - } - - PDFView.thumbnails[pageIndex++].draw(); - }, 500); -}, true); - window.addEventListener('scalechange', function scalechange(evt) { var customScaleOption = document.getElementById('customScaleOption'); customScaleOption.selected = false;