Spaces:
Sleeping
Sleeping
File size: 4,666 Bytes
b593f0b | 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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | // @flow
import DOM from '../../util/dom';
import type Point from '@mapbox/point-geometry';
const LEFT_BUTTON = 0;
const RIGHT_BUTTON = 2;
// the values for each button in MouseEvent.buttons
const BUTTONS_FLAGS = {
[LEFT_BUTTON]: 1,
[RIGHT_BUTTON]: 2
};
function buttonStillPressed(e: MouseEvent, button: number) {
const flag = BUTTONS_FLAGS[button];
return e.buttons === undefined || (e.buttons & flag) !== flag;
}
class MouseHandler {
_enabled: boolean;
_active: boolean;
_lastPoint: Point;
_eventButton: number;
_moved: boolean;
_clickTolerance: number;
constructor(options: { clickTolerance: number }) {
this.reset();
this._clickTolerance = options.clickTolerance || 1;
}
blur() {
this.reset();
}
reset() {
this._active = false;
this._moved = false;
delete this._lastPoint;
delete this._eventButton;
}
_correctButton(e: MouseEvent, button: number) { //eslint-disable-line
return false; // implemented by child
}
_move(lastPoint: Point, point: Point) { //eslint-disable-line
return {}; // implemented by child
}
mousedown(e: MouseEvent, point: Point) {
if (this._lastPoint) return;
const eventButton = DOM.mouseButton(e);
if (!this._correctButton(e, eventButton)) return;
this._lastPoint = point;
this._eventButton = eventButton;
}
mousemoveWindow(e: MouseEvent, point: Point) {
const lastPoint = this._lastPoint;
if (!lastPoint) return;
e.preventDefault();
if (buttonStillPressed(e, this._eventButton)) {
// Some browsers don't fire a `mouseup` when the mouseup occurs outside
// the window or iframe:
// https://github.com/mapbox/mapbox-gl-js/issues/4622
//
// If the button is no longer pressed during this `mousemove` it may have
// been released outside of the window or iframe.
this.reset();
return;
}
if (!this._moved && point.dist(lastPoint) < this._clickTolerance) return;
this._moved = true;
this._lastPoint = point;
// implemented by child class
return this._move(lastPoint, point);
}
mouseupWindow(e: MouseEvent) {
if (!this._lastPoint) return;
const eventButton = DOM.mouseButton(e);
if (eventButton !== this._eventButton) return;
if (this._moved) DOM.suppressClick();
this.reset();
}
enable() {
this._enabled = true;
}
disable() {
this._enabled = false;
this.reset();
}
isEnabled() {
return this._enabled;
}
isActive() {
return this._active;
}
}
export class MousePanHandler extends MouseHandler {
mousedown(e: MouseEvent, point: Point) {
super.mousedown(e, point);
if (this._lastPoint) this._active = true;
}
_correctButton(e: MouseEvent, button: number) {
return button === LEFT_BUTTON && !e.ctrlKey;
}
_move(lastPoint: Point, point: Point) {
return {
around: point,
panDelta: point.sub(lastPoint)
};
}
}
export class MouseRotateHandler extends MouseHandler {
_correctButton(e: MouseEvent, button: number) {
return (button === LEFT_BUTTON && e.ctrlKey) || (button === RIGHT_BUTTON);
}
_move(lastPoint: Point, point: Point) {
const degreesPerPixelMoved = 0.8;
const bearingDelta = (point.x - lastPoint.x) * degreesPerPixelMoved;
if (bearingDelta) {
this._active = true;
return {bearingDelta};
}
}
contextmenu(e: MouseEvent) {
// prevent browser context menu when necessary; we don't allow it with rotation
// because we can't discern rotation gesture start from contextmenu on Mac
e.preventDefault();
}
}
export class MousePitchHandler extends MouseHandler {
_correctButton(e: MouseEvent, button: number) {
return (button === LEFT_BUTTON && e.ctrlKey) || (button === RIGHT_BUTTON);
}
_move(lastPoint: Point, point: Point) {
const degreesPerPixelMoved = -0.5;
const pitchDelta = (point.y - lastPoint.y) * degreesPerPixelMoved;
if (pitchDelta) {
this._active = true;
return {pitchDelta};
}
}
contextmenu(e: MouseEvent) {
// prevent browser context menu when necessary; we don't allow it with rotation
// because we can't discern rotation gesture start from contextmenu on Mac
e.preventDefault();
}
}
|