/**
* IDMouse.js
*
* @module InputDetect
* @author natade (https://github.com/natade-jp)
* @license MIT
*/
import IDDraggableSwitch from "./IDDraggableSwitch.js";
import IDPosition from "./IDPosition.js";
/**
* マウス入力を管理するクラスです。
* 左・中央・右クリックの状態やドラッグ・ホイール回転・マウス座標の追跡を行い、複数ボタンの同時押しにも対応しています。
*/
export default class IDMouse {
/**
* マウスの入力情報を管理するクラス
* 左・中央・右ボタン、位置、ホイールなどをまとめて扱えます。
* @constructor
*/
constructor() {
this._initIDMouse();
}
/**
* 各プロパティを初期化します。
* @private
*/
_initIDMouse() {
/**
* 左ボタンの状態を管理するオブジェクト
* @type {IDDraggableSwitch}
*/
this.left = new IDDraggableSwitch(IDMouse.MOUSE_EVENTS.BUTTON1_MASK);
/**
* 中央ボタンの状態を管理するオブジェクト
* @type {IDDraggableSwitch}
*/
this.center = new IDDraggableSwitch(IDMouse.MOUSE_EVENTS.BUTTON2_MASK);
/**
* 右ボタンの状態を管理するオブジェクト
* @type {IDDraggableSwitch}
*/
this.right = new IDDraggableSwitch(IDMouse.MOUSE_EVENTS.BUTTON3_MASK);
/**
* 現在のマウス座標
* @type {IDPosition}
*/
this.position = new IDPosition();
/**
* ホイールの回転量
* @type {number}
*/
this.wheelrotation = 0;
}
/**
* このインスタンスの複製を作成します。
* @returns {IDMouse} 複製したIDMouseインスタンス
*/
clone() {
const ret = new IDMouse();
ret.left = this.left.clone();
ret.center = this.center.clone();
ret.right = this.right.clone();
ret.position = this.position.clone();
ret.wheelrotation = this.wheelrotation;
return ret;
}
/**
* マウスボタンが押された時の処理を行います。
* それぞれのボタンごとに対応する状態を更新します。
* @param {MouseEvent} mouseevent - マウスイベントまたは同等のオブジェクト
* @protected
*/
mousePressed(mouseevent) {
this.left.mousePressed(mouseevent);
this.center.mousePressed(mouseevent);
this.right.mousePressed(mouseevent);
}
/**
* マウスボタンが離された時の処理を行います。
* @param {MouseEvent} mouseevent - マウスイベントまたは同等のオブジェクト
* @protected
*/
mouseReleased(mouseevent) {
this.left.mouseReleased(mouseevent);
this.center.mouseReleased(mouseevent);
this.right.mouseReleased(mouseevent);
}
/**
* マウス移動時の処理を行います。
* それぞれのボタンのドラッグ状態や現在位置を更新します。
* @param {MouseEvent} mouseevent - マウスイベントまたは同等のオブジェクト
* @protected
*/
mouseMoved(mouseevent) {
this.left.mouseMoved(mouseevent);
this.center.mouseMoved(mouseevent);
this.right.mouseMoved(mouseevent);
this.position.x = this.left.client.x;
this.position.y = this.left.client.y;
}
/**
* ホイール回転イベントの処理を行います。
* @param {WheelEvent} event - ホイールイベントまたは同等のオブジェクト
* @protected
*/
mouseWheelMoved(event) {
if (event.deltaY !== 0) {
this.wheelrotation += event.deltaY > 0 ? -1 : 1;
}
}
/**
* マウスカーソルが要素外に出た場合の処理(状態リセット等)を行います。
* @protected
*/
focusLost() {
this.left.focusLost();
this.center.focusLost();
this.right.focusLost();
}
/**
* 他のIDMouseインスタンスへ現在の入力情報をコピーします。
* 各ボタンや位置、ホイール回転量が渡され、渡した後はホイール量がリセットされます。
* @param {IDMouse} c - 情報を受け取るIDMouseインスタンス
* @throws {string} cがIDMouseでない場合
*/
pickInput(c) {
if (!(c instanceof IDMouse)) {
throw "IllegalArgumentException";
}
this.left.pickInput(c.left);
this.center.pickInput(c.center);
this.right.pickInput(c.right);
c.position.set(this.position);
c.wheelrotation = this.wheelrotation;
this.wheelrotation = 0;
}
/**
* 指定した要素にマウス入力イベントリスナーを登録します。
* これにより、押下・移動・ホイール回転・フォーカスロスト等のイベントをこのクラスで検知できます。
* @param {HTMLElement} element - イベントリスナーを設定するDOM要素
*/
setListenerOnElement(element) {
const that = this;
/**
* @param {MouseEvent} e
*/
const mousePressed = function (e) {
that.mousePressed(e);
};
/**
* @param {MouseEvent} e
*/
const mouseReleased = function (e) {
that.mouseReleased(e);
};
/**
* @param {MouseEvent} e
*/
const mouseMoved = function (e) {
that.mouseMoved(e);
};
const focusLost = function () {
that.focusLost();
};
/**
* @param {WheelEvent} e
*/
const mouseWheelMoved = function (e) {
that.mouseWheelMoved(e);
e.preventDefault();
};
/**
* @param {Event} e
*/
const contextMenu = function (e) {
e.preventDefault();
};
element.style.cursor = "crosshair";
// 非選択化
element.style.userSelect = "none";
element.style.setProperty("-moz-user-select", "none");
element.style.setProperty("-webkit-user-select", "none");
element.style.setProperty("-ms-user-select", "none");
// メニュー非表示化
element.style.setProperty("-webkit-touch-callout", "none");
// タップのハイライトカラーを消す
element.style.setProperty("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
element.addEventListener("mousedown", mousePressed, false);
element.addEventListener("mouseup", mouseReleased, false);
element.addEventListener("mousemove", mouseMoved, false);
element.addEventListener("mouseout", focusLost, false);
element.addEventListener("wheel", mouseWheelMoved, false);
element.addEventListener("contextmenu", contextMenu, false);
}
}
/**
* マウスボタン番号の定数
* BUTTON1_MASK: 左ボタン, BUTTON2_MASK: 中央ボタン, BUTTON3_MASK: 右ボタン
* @enum {number}
*/
IDMouse.MOUSE_EVENTS = {
/**
* 左ボタン
* @type {number}
*/
BUTTON1_MASK: 0,
/**
* 中央ボタン
* @type {number}
*/
BUTTON2_MASK: 1,
/**
* 右ボタン
* @type {number}
*/
BUTTON3_MASK: 2
};