Maintain the current position in the document when zooming

This commit is contained in:
Jonas Jenwald 2014-01-11 12:57:33 +01:00
parent d6ed4f2631
commit 05c331c295
3 changed files with 87 additions and 33 deletions

View File

@ -400,16 +400,10 @@ var PageView = function pageView(container, id, scale,
this.viewport.convertToViewportPoint(x, y), this.viewport.convertToViewportPoint(x, y),
this.viewport.convertToViewportPoint(x + width, y + height) this.viewport.convertToViewportPoint(x + width, y + height)
]; ];
setTimeout(function pageViewScrollIntoViewRelayout() { var left = Math.min(boundingRect[0][0], boundingRect[1][0]);
// letting page to re-layout before scrolling var top = Math.min(boundingRect[0][1], boundingRect[1][1]);
var scale = PDFView.currentScale;
var x = Math.min(boundingRect[0][0], boundingRect[1][0]);
var y = Math.min(boundingRect[0][1], boundingRect[1][1]);
var width = Math.abs(boundingRect[0][0] - boundingRect[1][0]);
var height = Math.abs(boundingRect[0][1] - boundingRect[1][1]);
scrollIntoView(div, {left: x, top: y, width: width, height: height}); scrollIntoView(div, { left: left, top: top });
}, 0);
}; };
this.getTextContent = function pageviewGetTextContent() { this.getTextContent = function pageviewGetTextContent() {

View File

@ -20,6 +20,7 @@
var DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms var DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms
var SELECTOR = 'presentationControls'; var SELECTOR = 'presentationControls';
var DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1000; // in ms
var PresentationMode = { var PresentationMode = {
active: false, active: false,
@ -66,11 +67,38 @@ var PresentationMode = {
document.msFullscreenElement); document.msFullscreenElement);
}, },
/**
* Initialize a timeout that is used to reset PDFView.currentPosition when the
* browser transitions to fullscreen mode. Since resize events are triggered
* multiple times during the switch to fullscreen mode, this is necessary in
* order to prevent the page from being scrolled partially, or completely,
* out of view when Presentation Mode is enabled.
* Note: This is only an issue at certain zoom levels, e.g. 'page-width'.
*/
_setSwitchInProgress: function presentationMode_setSwitchInProgress() {
if (this.switchInProgress) {
clearTimeout(this.switchInProgress);
}
this.switchInProgress = setTimeout(function switchInProgressTimeout() {
delete this.switchInProgress;
}.bind(this), DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS);
PDFView.currentPosition = null;
},
_resetSwitchInProgress: function presentationMode_resetSwitchInProgress() {
if (this.switchInProgress) {
clearTimeout(this.switchInProgress);
delete this.switchInProgress;
}
},
request: function presentationModeRequest() { request: function presentationModeRequest() {
if (!PDFView.supportsFullscreen || this.isFullscreen || if (!PDFView.supportsFullscreen || this.isFullscreen ||
!this.viewer.hasChildNodes()) { !this.viewer.hasChildNodes()) {
return false; return false;
} }
this._setSwitchInProgress();
if (this.container.requestFullscreen) { if (this.container.requestFullscreen) {
this.container.requestFullscreen(); this.container.requestFullscreen();
@ -94,9 +122,15 @@ var PresentationMode = {
enter: function presentationModeEnter() { enter: function presentationModeEnter() {
this.active = true; this.active = true;
this._resetSwitchInProgress();
// Ensure that the correct page is scrolled into view when entering
// Presentation Mode, by waiting until fullscreen mode in enabled.
// Note: This is only necessary in non-Mozilla browsers.
setTimeout(function enterPresentationModeTimeout() {
PDFView.page = this.args.page; PDFView.page = this.args.page;
PDFView.setScale('page-fit', true); PDFView.setScale('page-fit', true);
}.bind(this), 0);
window.addEventListener('mousemove', this.mouseMove, false); window.addEventListener('mousemove', this.mouseMove, false);
window.addEventListener('mousedown', this.mouseDown, false); window.addEventListener('mousedown', this.mouseDown, false);
@ -109,18 +143,25 @@ var PresentationMode = {
}, },
exit: function presentationModeExit() { exit: function presentationModeExit() {
this.active = false;
var page = PDFView.page; var page = PDFView.page;
// Ensure that the correct page is scrolled into view when exiting
// Presentation Mode, by waiting until fullscreen mode is disabled.
// Note: This is only necessary in non-Mozilla browsers.
setTimeout(function exitPresentationModeTimeout() {
PDFView.setScale(this.args.previousScale); PDFView.setScale(this.args.previousScale);
PDFView.page = page; PDFView.page = page;
// Keep Presentation Mode active until the page is scrolled into view,
// to prevent issues in non-Mozilla browsers.
this.active = false;
this.args = null;
}.bind(this), 0);
window.removeEventListener('mousemove', this.mouseMove, false); window.removeEventListener('mousemove', this.mouseMove, false);
window.removeEventListener('mousedown', this.mouseDown, false); window.removeEventListener('mousedown', this.mouseDown, false);
window.removeEventListener('contextmenu', this.contextMenu, false); window.removeEventListener('contextmenu', this.contextMenu, false);
this.hideControls(); this.hideControls();
this.args = null;
PDFView.clearMouseScrollState(); PDFView.clearMouseScrollState();
HandTool.exitPresentationMode(); HandTool.exitPresentationMode();
this.container.removeAttribute('contextmenu'); this.container.removeAttribute('contextmenu');

View File

@ -40,6 +40,7 @@ var SCALE_SELECT_PADDING = 22;
var THUMBNAIL_SCROLL_MARGIN = -19; var THUMBNAIL_SCROLL_MARGIN = -19;
var USE_ONLY_CSS_ZOOM = false; var USE_ONLY_CSS_ZOOM = false;
var CLEANUP_TIMEOUT = 30000; var CLEANUP_TIMEOUT = 30000;
var IGNORE_CURRENT_POSITION_ON_ZOOM = false;
//#if B2G //#if B2G
//USE_ONLY_CSS_ZOOM = true; //USE_ONLY_CSS_ZOOM = true;
//#endif //#endif
@ -111,6 +112,7 @@ var PDFView = {
previousPageNumber: 1, previousPageNumber: 1,
isViewerEmbedded: (window.parent !== window), isViewerEmbedded: (window.parent !== window),
idleTimeout: null, idleTimeout: null,
currentPosition: null,
// called once when the document is loaded // called once when the document is loaded
initialize: function pdfViewInitialize() { initialize: function pdfViewInitialize() {
@ -219,7 +221,13 @@ var PDFView = {
this.currentScale = newScale; this.currentScale = newScale;
if (!noScroll) { if (!noScroll) {
this.pages[this.page - 1].scrollIntoView(); var page = this.page, dest;
if (this.currentPosition && !IGNORE_CURRENT_POSITION_ON_ZOOM) {
page = this.currentPosition.page;
dest = [null, { name: 'XYZ' }, this.currentPosition.left,
this.currentPosition.top, null];
}
this.pages[page - 1].scrollIntoView(dest);
} }
var event = document.createEvent('UIEvents'); var event = document.createEvent('UIEvents');
event.initUIEvent('scalechange', false, false, window, 0); event.initUIEvent('scalechange', false, false, window, 0);
@ -1049,6 +1057,9 @@ var PDFView = {
// Reset 'currentPageNumber', since otherwise the page's scale will be wrong // Reset 'currentPageNumber', since otherwise the page's scale will be wrong
// if 'currentPageNumber' is larger than the number of pages in the file. // if 'currentPageNumber' is larger than the number of pages in the file.
document.getElementById('pageNumber').value = currentPageNumber = 1; document.getElementById('pageNumber').value = currentPageNumber = 1;
// Reset the current position when loading a new file,
// to prevent displaying the wrong position in the document.
this.currentPosition = null;
if (PDFHistory.initialDestination) { if (PDFHistory.initialDestination) {
this.navigateTo(PDFHistory.initialDestination); this.navigateTo(PDFHistory.initialDestination);
@ -1307,7 +1318,7 @@ var PDFView = {
Math.max(0, currentHeight + viewHeight - bottom); Math.max(0, currentHeight + viewHeight - bottom);
percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0; percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0;
visible.push({ id: view.id, y: currentHeight, visible.push({ id: view.id, x: currentWidth, y: currentHeight,
view: view, percent: percentHeight }); view: view, percent: percentHeight });
} }
@ -1379,7 +1390,7 @@ var PDFView = {
}, },
rotatePages: function pdfViewRotatePages(delta) { rotatePages: function pdfViewRotatePages(delta) {
var currentPage = this.pages[this.page - 1];
this.pageRotation = (this.pageRotation + 360 + delta) % 360; this.pageRotation = (this.pageRotation + 360 + delta) % 360;
for (var i = 0, l = this.pages.length; i < l; i++) { for (var i = 0, l = this.pages.length; i < l; i++) {
@ -1392,19 +1403,13 @@ var PDFView = {
thumb.update(this.pageRotation); thumb.update(this.pageRotation);
} }
this.setScale(this.currentScaleValue, true); this.setScale(this.currentScaleValue, true, true);
this.renderHighestPriority(); this.renderHighestPriority();
var currentPage = this.pages[this.page - 1]; if (currentPage) {
if (!currentPage) {
return;
}
// Wait for presentation mode to take effect
setTimeout(function() {
currentPage.scrollIntoView(); currentPage.scrollIntoView();
}, 0); }
}, },
/** /**
@ -1615,6 +1620,11 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) {
PDFJS.verbosity = hashParams['verbosity'] | 0; PDFJS.verbosity = hashParams['verbosity'] | 0;
} }
if ('ignoreCurrentPositionOnZoom' in hashParams) {
IGNORE_CURRENT_POSITION_ON_ZOOM =
(hashParams['ignoreCurrentPositionOnZoom'] === 'true');
}
//#if !(FIREFOX || MOZCENTRAL) //#if !(FIREFOX || MOZCENTRAL)
var locale = navigator.language; var locale = navigator.language;
if ('locale' in hashParams) if ('locale' in hashParams)
@ -1812,17 +1822,26 @@ function updateViewarea() {
var pdfOpenParams = '#page=' + pageNumber; var pdfOpenParams = '#page=' + pageNumber;
pdfOpenParams += '&zoom=' + normalizedScaleValue; pdfOpenParams += '&zoom=' + normalizedScaleValue;
var currentPage = PDFView.pages[pageNumber - 1]; var currentPage = PDFView.pages[pageNumber - 1];
var topLeft = currentPage.getPagePoint(PDFView.container.scrollLeft, var container = PDFView.container;
(PDFView.container.scrollTop - firstPage.y)); var topLeft = currentPage.getPagePoint((container.scrollLeft - firstPage.x),
pdfOpenParams += ',' + Math.round(topLeft[0]) + ',' + Math.round(topLeft[1]); (container.scrollTop - firstPage.y));
var intLeft = Math.round(topLeft[0]);
var intTop = Math.round(topLeft[1]);
pdfOpenParams += ',' + intLeft + ',' + intTop;
if (PresentationMode.active || PresentationMode.switchInProgress) {
PDFView.currentPosition = null;
} else {
PDFView.currentPosition = { page: pageNumber, left: intLeft, top: intTop };
}
var store = PDFView.store; var store = PDFView.store;
store.initializedPromise.then(function() { store.initializedPromise.then(function() {
store.set('exists', true); store.set('exists', true);
store.set('page', pageNumber); store.set('page', pageNumber);
store.set('zoom', normalizedScaleValue); store.set('zoom', normalizedScaleValue);
store.set('scrollLeft', Math.round(topLeft[0])); store.set('scrollLeft', intLeft);
store.set('scrollTop', Math.round(topLeft[1])); store.set('scrollTop', intTop);
}); });
var href = PDFView.getAnchorUrl(pdfOpenParams); var href = PDFView.getAnchorUrl(pdfOpenParams);
document.getElementById('viewBookmark').href = href; document.getElementById('viewBookmark').href = href;