-
-
Notifications
You must be signed in to change notification settings - Fork 3k
/
PinchZoom.js
135 lines (115 loc) · 3.19 KB
/
PinchZoom.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* @module ol/interaction/PinchZoom
*/
import PointerInteraction, {
centroid as centroidFromPointers,
} from './Pointer.js';
import {FALSE} from '../functions.js';
/**
* @typedef {Object} Options
* @property {number} [duration=400] Animation duration in milliseconds.
*/
/**
* @classdesc
* Allows the user to zoom the map by pinching with two fingers
* on a touch screen.
* @api
*/
class PinchZoom extends PointerInteraction {
/**
* @param {Options} [options] Options.
*/
constructor(options) {
options = options ? options : {};
const pointerOptions = /** @type {import("./Pointer.js").Options} */ (
options
);
if (!pointerOptions.stopDown) {
pointerOptions.stopDown = FALSE;
}
super(pointerOptions);
/**
* @private
* @type {import("../coordinate.js").Coordinate}
*/
this.anchor_ = null;
/**
* @private
* @type {number}
*/
this.duration_ = options.duration !== undefined ? options.duration : 400;
/**
* @private
* @type {number|undefined}
*/
this.lastDistance_ = undefined;
/**
* @private
* @type {number}
*/
this.lastScaleDelta_ = 1;
}
/**
* Handle pointer drag events.
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
*/
handleDragEvent(mapBrowserEvent) {
let scaleDelta = 1.0;
const touch0 = this.targetPointers[0];
const touch1 = this.targetPointers[1];
const dx = touch0.clientX - touch1.clientX;
const dy = touch0.clientY - touch1.clientY;
// distance between touches
const distance = Math.sqrt(dx * dx + dy * dy);
if (this.lastDistance_ !== undefined) {
scaleDelta = this.lastDistance_ / distance;
}
this.lastDistance_ = distance;
const map = mapBrowserEvent.map;
const view = map.getView();
if (scaleDelta != 1.0) {
this.lastScaleDelta_ = scaleDelta;
}
// scale anchor point.
this.anchor_ = map.getCoordinateFromPixelInternal(
map.getEventPixel(centroidFromPointers(this.targetPointers)),
);
// scale, bypass the resolution constraint
map.render();
view.adjustResolutionInternal(scaleDelta, this.anchor_);
}
/**
* Handle pointer up events.
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
* @return {boolean} If the event was consumed.
*/
handleUpEvent(mapBrowserEvent) {
if (this.targetPointers.length < 2) {
const map = mapBrowserEvent.map;
const view = map.getView();
const direction = this.lastScaleDelta_ > 1 ? 1 : -1;
view.endInteraction(this.duration_, direction);
return false;
}
return true;
}
/**
* Handle pointer down events.
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
* @return {boolean} If the event was consumed.
*/
handleDownEvent(mapBrowserEvent) {
if (this.targetPointers.length >= 2) {
const map = mapBrowserEvent.map;
this.anchor_ = null;
this.lastDistance_ = undefined;
this.lastScaleDelta_ = 1;
if (!this.handlingDownUpSequence) {
map.getView().beginInteraction();
}
return true;
}
return false;
}
}
export default PinchZoom;