mirror of
https://github.com/zen-browser/pdf.js.git
synced 2025-07-09 01:35:43 +02:00
Add scrolling modes to web viewer
In addition to the default scrolling mode (vertical), this commit adds horizontal and wrapped scrolling, implemented primarily with CSS.
This commit is contained in:
parent
65c8549759
commit
91cbc185da
17 changed files with 665 additions and 27 deletions
|
@ -15,9 +15,9 @@
|
|||
|
||||
import {
|
||||
CSS_UNITS, DEFAULT_SCALE, DEFAULT_SCALE_VALUE, isPortraitOrientation,
|
||||
isValidRotation, MAX_AUTO_SCALE, NullL10n, PresentationModeState,
|
||||
RendererType, SCROLLBAR_PADDING, TextLayerMode, UNKNOWN_SCALE,
|
||||
VERTICAL_PADDING, watchScroll
|
||||
isValidRotation, MAX_AUTO_SCALE, moveToEndOfArray, NullL10n,
|
||||
PresentationModeState, RendererType, SCROLLBAR_PADDING, TextLayerMode,
|
||||
UNKNOWN_SCALE, VERTICAL_PADDING, watchScroll
|
||||
} from './ui_utils';
|
||||
import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue';
|
||||
import { AnnotationLayerBuilder } from './annotation_layer_builder';
|
||||
|
@ -29,6 +29,12 @@ import { TextLayerBuilder } from './text_layer_builder';
|
|||
|
||||
const DEFAULT_CACHE_SIZE = 10;
|
||||
|
||||
const ScrollMode = {
|
||||
VERTICAL: 0, // The default value.
|
||||
HORIZONTAL: 1,
|
||||
WRAPPED: 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} PDFViewerOptions
|
||||
* @property {HTMLDivElement} container - The container for the viewer element.
|
||||
|
@ -61,6 +67,10 @@ const DEFAULT_CACHE_SIZE = 10;
|
|||
* size in total pixels, i.e. width * height. Use -1 for no limit.
|
||||
* The default value is 4096 * 4096 (16 mega-pixels).
|
||||
* @property {IL10n} l10n - Localization service.
|
||||
* @property {number} scrollMode - (optional) The direction in which the
|
||||
* document pages should be laid out within the scrolling container. The
|
||||
* constants from {ScrollMode} should be used. The default value is
|
||||
* `ScrollMode.VERTICAL`.
|
||||
*/
|
||||
|
||||
function PDFPageViewBuffer(size) {
|
||||
|
@ -75,8 +85,24 @@ function PDFPageViewBuffer(size) {
|
|||
data.shift().destroy();
|
||||
}
|
||||
};
|
||||
this.resize = function(newSize) {
|
||||
/**
|
||||
* After calling resize, the size of the buffer will be newSize. The optional
|
||||
* parameter pagesToKeep is, if present, an array of pages to push to the back
|
||||
* of the buffer, delaying their destruction. The size of pagesToKeep has no
|
||||
* impact on the final size of the buffer; if pagesToKeep has length larger
|
||||
* than newSize, some of those pages will be destroyed anyway.
|
||||
*/
|
||||
this.resize = function(newSize, pagesToKeep) {
|
||||
size = newSize;
|
||||
if (pagesToKeep) {
|
||||
const pageIdsToKeep = new Set();
|
||||
for (let i = 0, iMax = pagesToKeep.length; i < iMax; ++i) {
|
||||
pageIdsToKeep.add(pagesToKeep[i].id);
|
||||
}
|
||||
moveToEndOfArray(data, function(page) {
|
||||
return pageIdsToKeep.has(page.id);
|
||||
});
|
||||
}
|
||||
while (data.length > size) {
|
||||
data.shift().destroy();
|
||||
}
|
||||
|
@ -126,6 +152,7 @@ class BaseViewer {
|
|||
this.useOnlyCssZoom = options.useOnlyCssZoom || false;
|
||||
this.maxCanvasPixels = options.maxCanvasPixels;
|
||||
this.l10n = options.l10n || NullL10n;
|
||||
this.scrollMode = options.scrollMode || ScrollMode.VERTICAL;
|
||||
|
||||
this.defaultRenderingQueue = !options.renderingQueue;
|
||||
if (this.defaultRenderingQueue) {
|
||||
|
@ -143,6 +170,7 @@ class BaseViewer {
|
|||
if (this.removePageBorders) {
|
||||
this.viewer.classList.add('removePageBorders');
|
||||
}
|
||||
this._updateScrollModeClasses();
|
||||
}
|
||||
|
||||
get pagesCount() {
|
||||
|
@ -557,6 +585,11 @@ class BaseViewer {
|
|||
0 : SCROLLBAR_PADDING;
|
||||
let vPadding = (this.isInPresentationMode || this.removePageBorders) ?
|
||||
0 : VERTICAL_PADDING;
|
||||
if (this.scrollMode === ScrollMode.HORIZONTAL) {
|
||||
const temp = hPadding;
|
||||
hPadding = vPadding;
|
||||
vPadding = temp;
|
||||
}
|
||||
let pageWidthScale = (this.container.clientWidth - hPadding) /
|
||||
currentPage.width * currentPage.scale;
|
||||
let pageHeightScale = (this.container.clientHeight - vPadding) /
|
||||
|
@ -733,10 +766,15 @@ class BaseViewer {
|
|||
});
|
||||
}
|
||||
|
||||
_resizeBuffer(numVisiblePages) {
|
||||
/**
|
||||
* visiblePages is optional; if present, it should be an array of pages and in
|
||||
* practice its length is going to be numVisiblePages, but this is not
|
||||
* required. The new size of the buffer depends only on numVisiblePages.
|
||||
*/
|
||||
_resizeBuffer(numVisiblePages, visiblePages) {
|
||||
let suggestedCacheSize = Math.max(DEFAULT_CACHE_SIZE,
|
||||
2 * numVisiblePages + 1);
|
||||
this._buffer.resize(suggestedCacheSize);
|
||||
this._buffer.resize(suggestedCacheSize, visiblePages);
|
||||
}
|
||||
|
||||
_updateLocation(firstPage) {
|
||||
|
@ -847,9 +885,11 @@ class BaseViewer {
|
|||
|
||||
forceRendering(currentlyVisiblePages) {
|
||||
let visiblePages = currentlyVisiblePages || this._getVisiblePages();
|
||||
let scrollAhead = this.scrollMode === ScrollMode.HORIZONTAL ?
|
||||
this.scroll.right : this.scroll.down;
|
||||
let pageView = this.renderingQueue.getHighestPriority(visiblePages,
|
||||
this._pages,
|
||||
this.scroll.down);
|
||||
scrollAhead);
|
||||
if (pageView) {
|
||||
this._ensurePdfPageLoaded(pageView).then(() => {
|
||||
this.renderingQueue.renderView(pageView);
|
||||
|
@ -957,8 +997,32 @@ class BaseViewer {
|
|||
};
|
||||
});
|
||||
}
|
||||
|
||||
setScrollMode(mode) {
|
||||
if (mode !== this.scrollMode) {
|
||||
this.scrollMode = mode;
|
||||
this._updateScrollModeClasses();
|
||||
this.eventBus.dispatch('scrollmodechanged', { mode, });
|
||||
const pageNumber = this._currentPageNumber;
|
||||
// Non-numeric scale modes can be sensitive to the scroll orientation.
|
||||
// Call this before re-scrolling to the current page, to ensure that any
|
||||
// changes in scale don't move the current page.
|
||||
if (isNaN(this._currentScaleValue)) {
|
||||
this._setScale(this._currentScaleValue, this.isInPresentationMode);
|
||||
}
|
||||
this.scrollPageIntoView({ pageNumber, });
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
_updateScrollModeClasses() {
|
||||
const mode = this.scrollMode, { classList, } = this.viewer;
|
||||
classList.toggle('scrollHorizontal', mode === ScrollMode.HORIZONTAL);
|
||||
classList.toggle('scrollWrapped', mode === ScrollMode.WRAPPED);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
BaseViewer,
|
||||
ScrollMode,
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue