package.src.ui.handler.mouse.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mapbox-gl Show documentation
Show all versions of mapbox-gl Show documentation
A WebGL interactive maps library
The newest version!
// @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();
}
}