Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5327)

Unified Diff: chrome/browser/resources/pdf/viewport.js

Issue 2400743002: Improved Pinch-Zoom for PDF. (Closed)
Patch Set: Small changes. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/resources/pdf/pdf.js ('k') | chrome/test/data/pdf/gesture_detector_test.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/resources/pdf/viewport.js
diff --git a/chrome/browser/resources/pdf/viewport.js b/chrome/browser/resources/pdf/viewport.js
index 18fb6c2ad403f4c8a49956f43a37bc776eaece6e..80a5a06ac646bb69e61dcda69a07bfb53a2ea208 100644
--- a/chrome/browser/resources/pdf/viewport.js
+++ b/chrome/browser/resources/pdf/viewport.js
@@ -15,6 +15,36 @@ function getIntersectionHeight(rect1, rect2) {
}
/**
+ * Makes sure that the scale level doesn't get out of the limits.
+ * @param {number} scale The new scale level.
+ * @return {number} The scale clamped within the limits.
+ */
+function clampScale(scale) {
+ return Math.min(5, Math.max(0.25, scale));
+}
+
+/**
+ * Computes vector between two points.
+ * @param {!Object} p1 The first point.
+ * @param {!Object} p2 The second point.
+ * @return {!Object} The vector.
+ */
+function vectorDelta(p1, p2) {
+ return {
+ x: p2.x - p1.x,
+ y: p2.y - p1.y
+ };
+}
+
+function frameToPluginCoordinate(coordinateInFrame) {
+ var container = $('plugin');
+ return {
+ x: coordinateInFrame.x - container.getBoundingClientRect().left,
+ y: coordinateInFrame.y - container.getBoundingClientRect().top
+ };
+}
+
+/**
* Create a new viewport.
* @constructor
* @param {Window} window the window
@@ -49,6 +79,11 @@ function Viewport(window,
this.fittingType_ = Viewport.FittingType.NONE;
this.defaultZoom_ = defaultZoom;
this.topToolbarHeight_ = topToolbarHeight;
+ this.prevScale_ = 1;
+ this.pinchPhase_ = Viewport.PinchPhase.PINCH_NONE;
+ this.pinchPanVector_ = null;
+ this.pinchCenter_ = null;
+ this.firstPinchCenterInFrame_ = null;
window.addEventListener('scroll', this.updateViewport_.bind(this));
window.addEventListener('resize', this.resize_.bind(this));
@@ -65,6 +100,19 @@ Viewport.FittingType = {
};
/**
+ * Enumeration of pinch states.
+ * This should match PinchPhase enum in pdf/out_of_process_instance.h
+ * @enum {number}
+ */
+Viewport.PinchPhase = {
+ PINCH_NONE: 0,
+ PINCH_START: 1,
+ PINCH_UPDATE_ZOOM_OUT: 2,
+ PINCH_UPDATE_ZOOM_IN: 3,
+ PINCH_END: 4
+};
+
+/**
* The increment to scroll a page by in pixels when up/down/left/right arrow
* keys are pressed. Usually we just let the browser handle scrolling on the
* window when these keys are pressed but in certain cases we need to simulate
@@ -227,6 +275,29 @@ Viewport.prototype = {
},
/**
+ * @type {Viewport.PinchPhase} The phase of the current pinch gesture for
+ * the viewport.
+ */
+ get pinchPhase() {
+ return this.pinchPhase_;
+ },
+
+ /**
+ * @type {Object} The panning caused by the current pinch gesture (as
+ * the deltas of the x and y coordinates).
+ */
+ get pinchPanVector() {
+ return this.pinchPanVector_;
+ },
+
+ /**
+ * @type {Object} The coordinates of the center of the current pinch gesture.
+ */
+ get pinchCenter() {
+ return this.pinchCenter_;
+ },
+
+ /**
* @private
* Used to wrap a function that might perform zooming on the viewport. This is
* required so that we can notify the plugin that zooming is in progress
@@ -266,6 +337,54 @@ Viewport.prototype = {
},
/**
+ * @private
+ * Sets the zoom of the viewport.
+ * Same as setZoomInternal_ but for pinch zoom we have some more operations.
+ * @param {number} scaleDelta The zoom delta.
+ * @param {!Object} center The pinch center in content coordinates.
+ */
+ setPinchZoomInternal_: function(scaleDelta, center) {
+ assert(this.allowedToChangeZoom_,
+ 'Called Viewport.setPinchZoomInternal_ without calling ' +
+ 'Viewport.mightZoom_.');
+ this.zoom_ = clampScale(this.zoom_ * scaleDelta);
+
+ var newCenterInContent = this.frameToContent(center);
+ var delta = {
+ x: (newCenterInContent.x - this.oldCenterInContent.x),
+ y: (newCenterInContent.y - this.oldCenterInContent.y)
+ };
+
+ // Record the scroll position (relative to the pinch center).
+ var currentScrollPos = {
+ x: this.position.x - delta.x * this.zoom_,
+ y: this.position.y - delta.y * this.zoom_
+ };
+
+ this.contentSizeChanged_();
+ // Scroll to the scaled scroll position.
+ this.position = {
+ x: currentScrollPos.x,
+ y: currentScrollPos.y
+ };
+ },
+
+ /**
+ * @private
+ * Converts a point from frame to content coordinates.
+ * @param {!Object} framePoint The frame coordinates.
+ * @return {!Object} The content coordinates.
+ */
+ frameToContent: function(framePoint) {
+ // TODO(mcnee) Add a helper Point class to avoid duplicating operations
+ // on plain {x,y} objects.
+ return {
+ x: (framePoint.x + this.position.x) / this.zoom_,
+ y: (framePoint.y + this.position.y) / this.zoom_
+ };
+ },
+
+ /**
* Sets the zoom to the given zoom level.
* @param {number} newZoom the zoom level to zoom to.
*/
@@ -499,6 +618,79 @@ Viewport.prototype = {
},
/**
+ * Pinch zoom event handler.
+ * @param {!Object} e The pinch event.
+ */
+ pinchZoom: function(e) {
+ this.mightZoom_(function() {
+ this.pinchPhase_ = e.direction == 'out' ?
+ Viewport.PinchPhase.PINCH_UPDATE_ZOOM_OUT :
+ Viewport.PinchPhase.PINCH_UPDATE_ZOOM_IN;
+
+ var scaleDelta = e.startScaleRatio / this.prevScale_;
+ this.pinchPanVector_ =
+ vectorDelta(e.center, this.firstPinchCenterInFrame_);
+
+ var needsScrollbars = this.documentNeedsScrollbars_(
+ clampScale(this.zoom_ * scaleDelta));
+
+ this.pinchCenter_ = e.center;
+
+ // If there's no horizontal scrolling, keep the content centered so the
+ // user can't zoom in on the non-content area.
+ // TODO(mcnee) Investigate other ways of scaling when we don't have
+ // horizontal scrolling. We want to keep the document centered,
+ // but this causes a potentially awkward transition when we start
+ // using the gesture center.
+ if (!needsScrollbars.horizontal) {
+ this.pinchCenter_ = {
+ x: this.window_.innerWidth / 2,
+ y: this.window_.innerHeight / 2
+ };
+ } else if (this.keepContentCentered_) {
+ this.oldCenterInContent =
+ this.frameToContent(frameToPluginCoordinate(e.center));
+ this.keepContentCentered_ = false;
+ }
+
+ this.setPinchZoomInternal_(
+ scaleDelta, frameToPluginCoordinate(e.center));
+ this.updateViewport_();
+ this.prevScale_ = e.startScaleRatio;
+ }.bind(this));
+ },
+
+ pinchZoomStart: function(e) {
+ this.pinchPhase_ = Viewport.PinchPhase.PINCH_START;
+ this.prevScale_ = 1;
+ this.oldCenterInContent =
+ this.frameToContent(frameToPluginCoordinate(e.center));
+
+ var needsScrollbars = this.documentNeedsScrollbars_(this.zoom_);
+ this.keepContentCentered_ = !needsScrollbars.horizontal;
+ // We keep track of begining of the pinch.
+ // By doing so we will be able to compute the pan distance.
+ this.firstPinchCenterInFrame_ = e.center;
+ },
+
+ pinchZoomEnd: function(e) {
+ this.mightZoom_(function() {
+ this.pinchPhase_ = Viewport.PinchPhase.PINCH_END;
+ var scaleDelta = e.startScaleRatio / this.prevScale_;
+ this.pinchCenter_ = e.center;
+
+ this.setPinchZoomInternal_(
+ scaleDelta, frameToPluginCoordinate(e.center));
+ this.updateViewport_();
+ }.bind(this));
+
+ this.pinchPhase_ = Viewport.PinchPhase.PINCH_NONE;
+ this.pinchPanVector_ = null;
+ this.pinchCenter_ = null;
+ this.firstPinchCenterInFrame_ = null;
+ },
+
+ /**
* Go to the given page index.
* @param {number} page the index of the page to go to. zero-based.
*/
« no previous file with comments | « chrome/browser/resources/pdf/pdf.js ('k') | chrome/test/data/pdf/gesture_detector_test.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698