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

Side by Side Diff: chrome/browser/resources/pdf/gesture_detector.js

Issue 2400743002: Improved Pinch-Zoom for PDF. (Closed)
Patch Set: Use our own touch gesture detection. 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 /**
8 * A class that listens for touch events and produces events when these
9 * touches form gestures (e.g. pinching).
10 */
11 class GestureDetector {
12 /**
13 * Constructs a GestureDetector.
14 * @param {!Element} element The element to monitor for touch gestures.
15 */
16 constructor(element) {
17 this.element_ = element;
18
19 this.element_.addEventListener('touchstart', this.onTouchStart_.bind(this));
20 this.element_.addEventListener('touchmove', this.onTouch_.bind(this));
21 this.element_.addEventListener('touchend', this.onTouch_.bind(this));
22 this.element_.addEventListener('touchcancel', this.onTouch_.bind(this));
23
24 this.pinchStartEvent_ = null;
25 this.lastEvent_ = null;
26
27 this.listeners_ = {
28 'pinchstart': [],
29 'pinchupdate': [],
30 'pinchend': []
31 };
32 }
33
34 /**
35 * Add a |listener| to be notified of |type| events.
36 * @param {string} type The event type to be notified for.
37 * @param {Function} listener The callback.
38 */
39 addEventListener(type, listener) {
40 if (this.listeners_[type]) {
dpapad 2016/10/31 23:02:23 Since you are already using ES6 in this file ("cla
Kevin McNee - google account 2016/11/07 23:08:27 Done.
41 this.listeners_[type].push(listener);
42 }
43 }
44
45 /**
46 * Call the relevant listeners with the given |pinchEvent|.
47 * @private
48 * @param {Object} pinchEvent The event to notify the listeners of.
49 */
50 notify_(pinchEvent) {
51 var listeners = this.listeners_[pinchEvent.type];
dpapad 2016/10/31 23:02:23 Nit(optional): s/var/let throughout this file?
Kevin McNee - google account 2016/11/07 23:08:27 Done.
52 var numListeners = listeners.length;
53 for (var i = 0; i < numListeners; i++) {
dpapad 2016/10/31 23:02:23 Nit for (let l of listeners) l(pinchEvent);
Kevin McNee - google account 2016/11/07 23:08:27 Done.
54 listeners[i](pinchEvent);
55 }
56 }
57
58 /**
59 * The callback for touchstart events on the element.
60 * @private
61 * @param {!TouchEvent} ev Touch event on the element.
62 */
63 onTouchStart_(ev) {
dpapad 2016/10/31 23:02:23 Let's be consistent within this file, s/ev/event (
Kevin McNee - google account 2016/11/07 23:08:27 Done.
64 // We must preventDefault if there is a two finger touch. By doing so
65 // native pinch-zoom does not interfere with our way of handling the event.
66 if (ev.touches.length == 2) {
67 ev.preventDefault();
68 this.pinchStartEvent_ = ev;
69 this.lastEvent_ = ev;
70 this.notify_({
71 type: 'pinchstart',
72 center: GestureDetector.center_(ev)
73 });
74 }
75 }
76
77 /**
78 * The callback for touch move, end, and cancel events on the element.
79 * @private
80 * @param {!TouchEvent} ev Touch event on the element.
81 */
82 onTouch_(ev) {
83 if (!this.pinchStartEvent_)
84 return;
85
86 // Check if the pinch ends with the current event.
87 if (ev.touches.length < 2 ||
88 this.lastEvent_.touches.length !== ev.touches.length) {
89 var startScaleRatio = GestureDetector.pinchScaleRatio_(
90 this.lastEvent_, this.pinchStartEvent_);
91 var center = GestureDetector.center_(this.lastEvent_);
92 var endEvent = {
93 type: 'pinchend',
94 startScaleRatio: startScaleRatio,
95 center: center
96 };
97 this.pinchStartEvent_ = null;
98 this.lastEvent_ = null;
99 this.notify_(endEvent);
100 return;
101 }
102
103 var scaleRatio = GestureDetector.pinchScaleRatio_(ev, this.lastEvent_);
104 var startScaleRatio = GestureDetector.pinchScaleRatio_(
105 ev, this.pinchStartEvent_);
106 var center = GestureDetector.center_(ev);
107 this.notify_({
108 type: 'pinchupdate',
109 scaleRatio: scaleRatio,
110 direction: scaleRatio > 1.0 ? 'in' : 'out',
111 startScaleRatio: startScaleRatio,
112 center: center
113 });
114
115 this.lastEvent_ = ev;
116 }
117
118 /**
119 * Computes the change in scale between this touch event
120 * and a previous one.
121 * @private
122 * @param {!TouchEvent} ev Latest touch event on the element.
123 * @param {!TouchEvent} prevEv A previous touch event on the element.
124 */
125 static pinchScaleRatio_(ev, prevEv) {
126 var distance1 = GestureDetector.distance_(prevEv);
127 var distance2 = GestureDetector.distance_(ev);
128 if (distance1 === 0)
dpapad 2016/10/31 23:02:23 return distance1 === 0 ? null : distance2 / distan
Kevin McNee - google account 2016/11/07 23:08:27 Done.
129 return null;
130 return distance2 / distance1;
131 }
132
133 /**
134 * Computes the distance between fingers.
135 * @private
136 * @param {!TouchEvent} ev Touch event with at least 2 touch points.
137 * @return {number} Distance between touch[0] and touch[1].
138 */
139 static distance_(ev) {
140 var touch1 = ev.touches[0];
141 var touch2 = ev.touches[1];
142 var dx = touch1.clientX - touch2.clientX;
143 var dy = touch1.clientY - touch2.clientY;
144 return Math.sqrt(dx * dx + dy * dy);
145 }
146
147 /**
148 * Computes the midpoint between fingers.
149 * @private
150 * @param {!TouchEvent} ev Touch event with at least 2 touch points.
151 * @return {Object} Midpoint between touch[0] and touch[1].
152 */
153 static center_(ev) {
154 var touch1 = ev.touches[0];
155 var touch2 = ev.touches[1];
156 return {
157 x: (touch1.clientX + touch2.clientX) / 2,
158 y: (touch1.clientY + touch2.clientY) / 2
159 };
160 }
161 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698