115 lines
3.3 KiB
TypeScript
115 lines
3.3 KiB
TypeScript
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 }; |