import { Plugin } from './Plugin';
const MOUSE_EDGES_OPTIONS = {
radius: null,
distance: null,
top: null,
bottom: null,
left: null,
right: null,
speed: 8,
reverse: false,
noDecelerate: false,
linear: false,
allowButtons: false,
};
/**
* Scroll viewport when mouse hovers near one of the edges.
*
* @event mouse-edge-start(Viewport) emitted when mouse-edge starts
* @event mouse-edge-end(Viewport) emitted when mouse-edge ends
*/
export class MouseEdges extends Plugin {
/**
* This is called by {@link Viewport.mouseEdges}.
*/
constructor(parent, options = {}) {
super(parent);
this.options = Object.assign({}, MOUSE_EDGES_OPTIONS, options);
this.reverse = this.options.reverse ? 1 : -1;
this.radiusSquared = typeof this.options.radius === 'number' ? Math.pow(this.options.radius, 2) : null;
this.resize();
}
resize() {
const distance = this.options.distance;
if (distance !== null) {
this.left = distance;
this.top = distance;
this.right = this.parent.screenWidth - distance;
this.bottom = this.parent.screenHeight - distance;
}
else if (!this.options.radius) {
this.left = this.options.left;
this.top = this.options.top;
this.right = this.options.right === null ? null : this.parent.screenWidth - this.options.right;
this.bottom = this.options.bottom === null ? null : this.parent.screenHeight - this.options.bottom;
}
}
down() {
if (this.paused) {
return false;
}
if (!this.options.allowButtons) {
this.horizontal = this.vertical = null;
}
return false;
}
move(event) {
if (this.paused) {
return false;
}
if ((event.data.pointerType !== 'mouse' && event.data.identifier !== 1)
|| (!this.options.allowButtons && event.data.buttons !== 0)) {
return false;
}
const x = event.data.global.x;
const y = event.data.global.y;
if (this.radiusSquared) {
const center = this.parent.toScreen(this.parent.center);
const distance = Math.pow(center.x - x, 2) + Math.pow(center.y - y, 2);
if (distance >= this.radiusSquared) {
const angle = Math.atan2(center.y - y, center.x - x);
if (this.options.linear) {
this.horizontal = Math.round(Math.cos(angle)) * this.options.speed * this.reverse * (60 / 1000);
this.vertical = Math.round(Math.sin(angle)) * this.options.speed * this.reverse * (60 / 1000);
}
else {
this.horizontal = Math.cos(angle) * this.options.speed * this.reverse * (60 / 1000);
this.vertical = Math.sin(angle) * this.options.speed * this.reverse * (60 / 1000);
}
}
else {
if (this.horizontal) {
this.decelerateHorizontal();
}
if (this.vertical) {
this.decelerateVertical();
}
this.horizontal = this.vertical = 0;
}
}
else {
if (this.left !== null && x < this.left) {
this.horizontal = Number(this.reverse) * this.options.speed * (60 / 1000);
}
else if (this.right !== null && x > this.right) {
this.horizontal = -1 * this.reverse * this.options.speed * (60 / 1000);
}
else {
this.decelerateHorizontal();
this.horizontal = 0;
}
if (this.top !== null && y < this.top) {
this.vertical = Number(this.reverse) * this.options.speed * (60 / 1000);
}
else if (this.bottom !== null && y > this.bottom) {
this.vertical = -1 * this.reverse * this.options.speed * (60 / 1000);
}
else {
this.decelerateVertical();
this.vertical = 0;
}
}
return false;
}
decelerateHorizontal() {
const decelerate = this.parent.plugins.get('decelerate', true);
if (this.horizontal && decelerate && !this.options.noDecelerate) {
decelerate.activate({ x: (this.horizontal * this.options.speed * this.reverse) / (1000 / 60) });
}
}
decelerateVertical() {
const decelerate = this.parent.plugins.get('decelerate', true);
if (this.vertical && decelerate && !this.options.noDecelerate) {
decelerate.activate({ y: (this.vertical * this.options.speed * this.reverse) / (1000 / 60) });
}
}
up() {
if (this.paused) {
return false;
}
if (this.horizontal) {
this.decelerateHorizontal();
}
if (this.vertical) {
this.decelerateVertical();
}
this.horizontal = this.vertical = null;
return false;
}
update() {
if (this.paused) {
return;
}
if (this.horizontal || this.vertical) {
const center = this.parent.center;
if (this.horizontal) {
center.x += this.horizontal * this.options.speed;
}
if (this.vertical) {
center.y += this.vertical * this.options.speed;
}
this.parent.moveCenter(center);
this.parent.emit('moved', { viewport: this.parent, type: 'mouse-edges' });
}
}
}