@studiometa/js-toolkit
Version:
A set of useful little bits of JavaScript to boost your project! 🚀
130 lines (129 loc) • 3.22 kB
JavaScript
import { AbstractService } from "./AbstractService.js";
import { ONCE_CAPTURE_EVENT_OPTIONS, PASSIVE_CAPTURE_EVENT_OPTIONS } from "./utils.js";
class PointerService extends AbstractService {
static config = [
[
() => document,
[
["mouseenter", ONCE_CAPTURE_EVENT_OPTIONS],
["mousemove", PASSIVE_CAPTURE_EVENT_OPTIONS],
["touchmove", PASSIVE_CAPTURE_EVENT_OPTIONS],
["mousedown", PASSIVE_CAPTURE_EVENT_OPTIONS],
["touchstart", PASSIVE_CAPTURE_EVENT_OPTIONS],
["mouseup", PASSIVE_CAPTURE_EVENT_OPTIONS],
["touchend", PASSIVE_CAPTURE_EVENT_OPTIONS]
]
]
];
target;
props = {
event: null,
isDown: false,
x: 0,
y: 0,
changed: {
x: false,
y: false
},
last: {
x: 0,
y: 0
},
delta: {
x: 0,
y: 0
},
progress: {
x: 0.5,
y: 0.5
},
max: {
x: 0,
y: 0
}
};
constructor(target) {
super();
this.target = target;
const targetSize = this.getTargetSize();
this.props.x = this.props.last.x = targetSize.x / 2;
this.props.y = this.props.last.y = targetSize.y / 2;
this.props.max.x = targetSize.width;
this.props.max.y = targetSize.height;
}
isTouchEvent(event) {
return typeof TouchEvent !== "undefined" && event instanceof TouchEvent;
}
getTargetSize() {
const { target } = this;
return target instanceof Element ? target.getBoundingClientRect() : {
width: window.innerWidth,
height: window.innerHeight,
x: 0,
y: 0
};
}
/**
* Update the pointer positions.
*/
updateProps(event) {
const { props } = this;
props.event = event;
const yLast = props.y;
const xLast = props.x;
const targetSize = this.getTargetSize();
let y = this.isTouchEvent(event) ? event.touches[0]?.clientY : event.clientY;
y -= targetSize.y;
if (y !== props.y) {
props.y = y;
}
let x = this.isTouchEvent(event) ? event.touches[0]?.clientX : event.clientX;
x -= targetSize.x;
if (x !== props.x) {
props.x = x;
}
props.changed.x = props.x !== xLast;
props.changed.y = props.y !== yLast;
props.last.x = xLast;
props.last.y = yLast;
props.delta.x = props.x - xLast;
props.delta.y = props.y - yLast;
props.max.x = targetSize.width;
props.max.y = targetSize.height;
props.progress.x = props.x / props.max.x;
props.progress.y = props.y / props.max.y;
return props;
}
/**
* Handle events.
*
* @todo handle scroll as well
*/
handleEvent(event) {
switch (event.type) {
case "mouseenter":
case "mousemove":
case "touchmove":
this.trigger(this.updateProps(event));
break;
case "mousedown":
case "touchstart":
this.props.isDown = true;
this.trigger(this.props);
break;
case "mouseup":
case "touchend":
this.props.isDown = false;
this.trigger(this.props);
break;
}
}
}
function usePointer(target = window) {
return PointerService.getInstance([target], target);
}
export {
PointerService,
usePointer
};
//# sourceMappingURL=PointerService.js.map