UNPKG

@pmndrs/handle

Version:

framework agnostic expandable handle implementation for threejs

70 lines (69 loc) 2.16 kB
import { getVoidObject } from '@pmndrs/pointer-events'; import { Vector2 } from 'three'; export class ScreenHandleStore { apply; getInitial; map = new Map(); initial; constructor(apply, getInitial) { this.apply = apply; this.getInitial = getInitial; this.initial = getInitial(); } bind(scene) { const down = this.onPointerDown.bind(this); const up = this.onPointerUp.bind(this); const move = this.onPointerMove.bind(this); const voidObject = getVoidObject(scene); voidObject.addEventListener('pointermove', move); voidObject.addEventListener('pointerdown', down); voidObject.addEventListener('pointerup', up); return () => { voidObject.removeEventListener('pointermove', move); voidObject.removeEventListener('pointerdown', down); voidObject.removeEventListener('pointerup', up); }; } onPointerDown(e) { if (e.intersection.details.type != 'screen-ray') { return; } e.target.setPointerCapture(e.pointerId); this.map.set(e.pointerId, { initialScreenPosition: new Vector2(), currentScreenPosition: e.intersection.details.screenPoint.clone(), initialEvent: e, latestEvent: e, }); this.save(); } onPointerUp(e) { if (!this.map.delete(e.pointerId)) { return; } this.save(); } onPointerMove(e) { if (e.intersection.details.type != 'screen-ray') { return; } const entry = this.map.get(e.pointerId); if (entry == null) { return; } entry.latestEvent = e; entry.currentScreenPosition.copy(e.intersection.details.screenPoint); } save() { for (const entry of this.map.values()) { entry.initialScreenPosition.copy(entry.currentScreenPosition); } this.initial = this.getInitial(); } update() { if (this.map.size === 0) { return; } this.apply(this.initial, this.map); } }