mr-tap
Version:
A tap library, abstracts away from mouse/touch providing source agnostic sync access to the user input.
209 lines (174 loc) • 5.83 kB
JavaScript
/**
* @class
* @name Tap
* @description Tap is instintiated by {@link Taps}, and provides information about the input, its state and coordinates. It is source agnostic, and behaves identical between mouse and touch.
* @property {boolean} start True when tap been just created, equivalent to mousedown and touchstart.
* @property {boolean} up True when tap is ended, equivalent to mouseup, touchend, touchcancel. It can be in that state only once, and will be removed after.
* @property {boolean} click True when tap is considered a click. It can be in that state only once, and will be removed after.
* @property {boolean} dragstart True when tap is started dragging, which happens when either: tap duration is long enough and/or it is moved away from initial position enough. It will be in that state once, and guarantees to have `dragend` state instead of `click` state.
* @property {boolean} drag True when tap is dragging. It will be in that state from `dragstart` till the end of a tap.
* @property {boolean} dragend True when tap is ended dragging. It will be in that state only if previously was in `dragstart`, and tap will be removed after.
* @property {boolean} timestamp Milliseconds timestamp of when tap has started.
* @property {boolean} mouse True when tap originated from mouse input.
* @property {null|number} button If originated from mouse, a button number, otherwise null.
* @property {number} x X current coordinate of a tap, where 0 - is left.
* @property {number} y Y current coordinate of a tap, where 0 - is top.
* @property {number} sx X coordinate of where tap started.
* @property {number} sy Y coordinate of where tap started.
* @property {number} dx X distance of a tap traveled since previous update.
* @property {number} dy Y distance of a tap traveled since previous update.
* @example
* // clicking
*
* for(const tap of taps.click) {
* // pick an object based on tap coordinates
* const object = pickObject(tap.x, tap.y);
* if (! object) continue;
*
* object.interact();
* }
* @example
* // dragging
*
* // grab an object for dragstart taps
* for(const tap of taps.dragstart) {
* // pick an object based on tap start coordinates
* const object = pickObject(tap.sx, tap.sy);
* // remember that object against a tap
* tap.object = object;
* }
*
* // move an objects for drag taps
* for(const tap of taps.drag) {
* // ensure we have an object
* if (! tap.object) continue;
*
* // set position of a dragged object to tap coordinates
* tap.object.setPosition(tap.x, tap.y);
* }
*
* // throw an object for dragend taps
* for(const tap of taps.dragend) {
* // ensure we have an object
* if (! tap.object) continue;
*
* // dt - delta time, to correct for a variable FPS
* tap.object.setLinearVelocity(tap.dx * dt, tap.dy * dt);
* }
*/
class Tap {
constructor(taps, id) {
this._taps = taps;
this._id = id;
this._timestamp = Date.now();
this._sx = 0;
this._sy = 0;
this._x = 0;
this._y = 0;
this._lx = 0;
this._ly = 0;
this._dx = 0;
this._dy = 0;
this._mouse = false;
this._button = null;
this._start = true;
this._started = false;
this._up = false;
this._click = false;
this._drag = false;
this._dragstart = false;
this._dragend = false;
}
change(evt) {
this._x = evt.clientX;
this._y = evt.clientY;
}
update() {
if (this._start && ! this._started) {
this._started = true;
} else if (this._started && this._start) {
this._start = false;
}
// check if needs removing
if (this._up) {
this._taps._index.delete(this._id);
return;
}
if (this._dragstart) {
this._dragstart = false;
}
// check if dragging
if (! this._drag) {
const dx = this._sx - this._x;
const dy = this._sy - this._y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist > this._taps._dragDistance || (Date.now() - this._timestamp) > this._taps._dragDelay) {
this._dragstart = true;
this._drag = true;
}
}
// check if tap is released
if (this._release) {
this._down = false;
this._up = true;
if (this._drag) {
this._dragend = true;
} else {
this._click = true;
}
}
this._dx = this._x - this._lx;
this._dy = this._y - this._ly;
this._lx = this._x;
this._ly = this._y;
}
get id() {
return this._id;
}
get start() {
return this._start;
}
get up() {
return this._up;
}
get click() {
return this._click;
}
get dragstart() {
return this._dragstart;
}
get drag() {
return this._drag;
}
get dragend() {
return this._dragend;
}
get timestamp() {
return this._timestamp;
}
get mouse() {
return this._mouse;
}
get button() {
return this._button;
}
get x() {
return this._x;
}
get y() {
return this._y;
}
get sx() {
return this._sx;
}
get sy() {
return this._sy;
}
get dx() {
return this._dx;
}
get dy() {
return this._dy;
}
}
export default Tap;