105 lines
2.9 KiB
TypeScript
105 lines
2.9 KiB
TypeScript
|
import { $EventManager, $EventMap } from "./$EventManager";
|
||
|
import { type $Node } from "./node/$Node";
|
||
|
|
||
|
export class $PointerManager extends $EventManager<$PointerManagerEventMap> {
|
||
|
$node: $Node;
|
||
|
map = new Map<number, $Pointer>();
|
||
|
constructor($node: $Node) {
|
||
|
super();
|
||
|
this.$node = $node;
|
||
|
this.$node.on('pointerdown', (e) => this.down(e))
|
||
|
this.$node.on('pointerup', (e) => this.up(e))
|
||
|
this.$node.on('pointermove', (e) => this.move(e))
|
||
|
this.$node.on('pointercancel', (e) => this.cancel(e))
|
||
|
}
|
||
|
|
||
|
protected down(e: PointerEvent) {
|
||
|
const pointer = new $Pointer(this, this.toData(e), $(e.target!))
|
||
|
this.map.set(pointer.id, pointer);
|
||
|
this.fire('down', pointer, e);
|
||
|
}
|
||
|
|
||
|
protected up(e: PointerEvent) {
|
||
|
const pointer = this.map.get(e.pointerId);
|
||
|
if (!pointer) return;
|
||
|
this.map.delete(e.pointerId);
|
||
|
this.fire('up', pointer, e);
|
||
|
}
|
||
|
|
||
|
protected move(e: PointerEvent) {
|
||
|
const pointer = this.map.get(e.pointerId);
|
||
|
if (!pointer) return;
|
||
|
this.map.set(pointer.id, pointer);
|
||
|
pointer.update(this.toData(e));
|
||
|
this.fire('move', pointer, e);
|
||
|
}
|
||
|
|
||
|
protected cancel(e: PointerEvent) {
|
||
|
const pointer = this.map.get(e.pointerId);
|
||
|
if (!pointer) return;
|
||
|
pointer.update(this.toData(e));
|
||
|
this.map.delete(pointer.id);
|
||
|
this.fire('cancel', pointer, e);
|
||
|
}
|
||
|
|
||
|
protected toData(e: PointerEvent): $PointerData {
|
||
|
return {
|
||
|
id: e.pointerId,
|
||
|
type: e.pointerType as PointerType,
|
||
|
width: e.width,
|
||
|
height: e.height,
|
||
|
x: e.x,
|
||
|
y: e.y,
|
||
|
movement_x: e.movementX,
|
||
|
movement_y: e.movementY
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export interface $PointerManagerEventMap extends $EventMap {
|
||
|
up: [$Pointer, MouseEvent];
|
||
|
down: [$Pointer, MouseEvent];
|
||
|
move: [$Pointer, MouseEvent];
|
||
|
cancel: [$Pointer, MouseEvent];
|
||
|
}
|
||
|
|
||
|
export interface $Pointer extends $PointerData {}
|
||
|
export class $Pointer {
|
||
|
initial_x: number;
|
||
|
initial_y: number;
|
||
|
$target: $Node;
|
||
|
protected manager: $PointerManager;
|
||
|
constructor(manager: $PointerManager, data: $PointerData, target: $Node) {
|
||
|
Object.assign(this, data);
|
||
|
this.manager = manager;
|
||
|
this.$target = target;
|
||
|
this.initial_x = data.x;
|
||
|
this.initial_y = data.y;
|
||
|
}
|
||
|
|
||
|
get move_x() { return this.x - this.initial_x }
|
||
|
get move_y() { return this.y - this.initial_y }
|
||
|
|
||
|
update(data: $PointerData) {
|
||
|
Object.assign(this, data);
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
delete() {
|
||
|
this.manager.map.delete(this.id);
|
||
|
return this;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export interface $PointerData {
|
||
|
id: number;
|
||
|
type: PointerType;
|
||
|
width: number;
|
||
|
height: number;
|
||
|
x: number;
|
||
|
y: number;
|
||
|
movement_x: number;
|
||
|
movement_y: number;
|
||
|
}
|
||
|
|
||
|
export type PointerType = 'mouse' | 'pen' | 'touch'
|