AltitudeWeb/frontend/src/app/pages/particles/services/input-handler.service.ts

106 lines
3.4 KiB
TypeScript
Raw Normal View History

import { Injectable, ElementRef } from '@angular/core';
import * as THREE from 'three';
import { RendererService } from './renderer.service';
import { IntersectionPlaneService } from './intersection-plane.service';
import { ParticleManagerService } from './particle-manager.service';
/**
* Service responsible for handling user input interactions
*/
@Injectable({
providedIn: 'root'
})
export class InputHandlerService {
private raycaster = new THREE.Raycaster();
private mouse = new THREE.Vector2();
private isDragging = false;
private mouseDownTime = 0;
constructor(
private rendererService: RendererService,
private intersectionPlaneService: IntersectionPlaneService,
private particleManagerService: ParticleManagerService
) {}
/**
* Initializes input event listeners
*/
initializeInputHandlers(rendererElement: HTMLElement): void {
rendererElement.addEventListener('mousedown', this.onMouseDown.bind(this));
rendererElement.addEventListener('mouseup', this.onMouseUp.bind(this));
rendererElement.addEventListener('mousemove', this.onMouseMove.bind(this));
window.addEventListener('resize', this.onWindowResize.bind(this));
}
/**
* Handles mouse down event
*/
private onMouseDown(event: MouseEvent): void {
this.isDragging = false;
this.mouseDownTime = Date.now();
}
/**
* Handles mouse up event
*/
private onMouseUp(event: MouseEvent): void {
// If mouse was down for less than 200ms and didn't move much, consider it a click, not a drag
if (Date.now() - this.mouseDownTime < 200 && !this.isDragging) {
this.handlePlaneClick(event);
}
this.isDragging = false;
}
/**
* Handles mouse move event
*/
private onMouseMove(event: MouseEvent): void {
// If mouse moves while button is pressed, it's a drag
if (event.buttons > 0) {
this.isDragging = true;
}
}
/**
* Handles mouse click on the plane
*/
private handlePlaneClick(event: MouseEvent): void {
// Calculate mouse position in normalized device coordinates
const rect = this.rendererService.renderer.domElement.getBoundingClientRect();
this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
// Update the picking ray with the camera and mouse position
this.raycaster.setFromCamera(this.mouse, this.rendererService.camera);
// Calculate objects intersecting the picking ray
const intersects = this.raycaster.intersectObject(this.intersectionPlaneService.getIntersectionPlane());
if (intersects.length > 0) {
const point = intersects[0].point;
this.particleManagerService.addParticle(point.x, point.y, point.z);
}
}
/**
* Handles window resize event
*/
private onWindowResize(): void {
// This is delegated to the renderer service
const container = this.rendererService.renderer.domElement.parentElement;
if (container) {
this.rendererService.onWindowResize(new ElementRef(container));
}
}
/**
* Removes event listeners
*/
cleanup(rendererElement: HTMLElement): void {
rendererElement.removeEventListener('mousedown', this.onMouseDown.bind(this));
rendererElement.removeEventListener('mouseup', this.onMouseUp.bind(this));
rendererElement.removeEventListener('mousemove', this.onMouseMove.bind(this));
window.removeEventListener('resize', this.onWindowResize.bind(this));
}
}