import { Vector2, WebGLRenderer } from 'three'; class SelectionHelper { element: HTMLDivElement; renderer: WebGLRenderer; startPoint: Vector2; pointTopLeft: Vector2; pointBottomRight: Vector2; isDown: boolean; enabled: boolean; constructor(renderer: WebGLRenderer) { this.element = document.createElement('div'); this.element.style.position = 'fixed'; this.element.style.border = '1px solid #55aaff'; this.element.style.backgroundColor = 'rgba(75, 160, 255, 0.3)'; this.element.style.pointerEvents = 'none'; this.element.style.display = 'none'; this.renderer = renderer; this.startPoint = new Vector2(); this.pointTopLeft = new Vector2(); this.pointBottomRight = new Vector2(); this.isDown = false; this.enabled = true; this.onPointerDown = this.onPointerDown.bind(this); this.onPointerMove = this.onPointerMove.bind(this); this.onPointerUp = this.onPointerUp.bind(this); this.renderer.domElement.addEventListener('pointerdown', this.onPointerDown); this.renderer.domElement.addEventListener('pointermove', this.onPointerMove); this.renderer.domElement.addEventListener('pointerup', this.onPointerUp); window.addEventListener("blur", this.cleanup.bind(this)); } dispose() { this.enabled = false; this.isDown = false; this.cleanup(); this.renderer.domElement.removeEventListener("pointerdown", this.onPointerDown); this.renderer.domElement.removeEventListener("pointermove", this.onPointerMove); this.renderer.domElement.removeEventListener("pointerup", this.onPointerUp); window.removeEventListener("blur", this.cleanup); } private cleanup() { this.isDown = false; this.element.style.display = 'none'; if (this.element.parentElement) { this.element.parentElement.removeChild(this.element); } } onPointerDown(event: PointerEvent) { if (!this.enabled || !event.ctrlKey || event.button !== 0) return; this.isDown = true; this.onSelectStart(event); } onPointerMove(event: PointerEvent) { if (!this.enabled || !this.isDown || !event.ctrlKey) return; this.onSelectMove(event); } onPointerUp() { if (!this.enabled) return; this.isDown = false; this.onSelectOver(); } onSelectStart(event: PointerEvent) { this.element.style.display = 'none'; this.renderer.domElement.parentElement?.appendChild(this.element); this.element.style.left = `${event.clientX}px`; this.element.style.top = `${event.clientY}px`; this.element.style.width = '0px'; this.element.style.height = '0px'; this.startPoint.x = event.clientX; this.startPoint.y = event.clientY; } onSelectMove(event: PointerEvent) { if (!this.isDown) return; this.element.style.display = 'block'; this.pointBottomRight.x = Math.max(this.startPoint.x, event.clientX); this.pointBottomRight.y = Math.max(this.startPoint.y, event.clientY); this.pointTopLeft.x = Math.min(this.startPoint.x, event.clientX); this.pointTopLeft.y = Math.min(this.startPoint.y, event.clientY); this.element.style.left = `${this.pointTopLeft.x}px`; this.element.style.top = `${this.pointTopLeft.y}px`; this.element.style.width = `${this.pointBottomRight.x - this.pointTopLeft.x}px`; this.element.style.height = `${this.pointBottomRight.y - this.pointTopLeft.y}px`; } onSelectOver() { this.element.style.display = 'none'; if (this.element.parentElement) { this.element.parentElement.removeChild(this.element); } } } export { SelectionHelper };