Object Events
Object Events is an API that allows you to forward pointer events to a THREE.js object, usually in a custom abstractions.
There are 2 ways to use Object Events API.
objectEvents
Section titled “objectEvents”This is a more direct way to use the API. It is useful for cases where you control the events you want to forward to the underlying THREE.js object, like in using directives guide.
@Directive({ selector: "ngt-mesh[cursor]" })export class Cursor { constructor() { const document = inject(DOCUMENT); const elementRef = inject<ElementRef<THREE.Mesh>>(ElementRef); const nativeElement = elementRef.nativeElement;
if (nativeElement.isMesh) { objectEvents(() => nativeElement, { pointerover: () => { document.body.style.cursor = "pointer"; }, pointerout: () => { document.body.style.cursor = "default"; }, }); } }}Then all <ngt-mesh cursor> will have pointerover and pointerout events forwarded to the underlying THREE.Mesh object.
NgtObjectEvents
Section titled “NgtObjectEvents”This is intended to be used as a hostDirectives on a custom abstraction. This is useful for cases where you don’t know which events the abstraction’s consumers will use. NgtObjectEvents calls objectEvents internally.
@Component({ selector: 'app-my-mesh', template: ` <ngt-mesh #mesh> <!-- mesh contents --> </ngt-mesh> `, hostDirectives: [{ directive: NgtObjectEvents, outputs: [ 'click', 'pointerover', 'pointerout', // ... other events you want to expose ] }]})export class MyMesh { private meshRef = viewChild.required<ElementRef<THREE.Mesh>>('mesh');
constructor() { const objectEvents = inject(NgtObjectEvents, { host: true }); objectEvents.ngtObjectEvents.set(this.meshRef); }}ngtObjectEvents is a Model Input that can accept:
- an
ElementRef<THREE.Object3D> - a
THREE.Object3D - a
Signal<ElementRef<THREE.Object3D> | THREE.Object3D>
How it works
Section titled “How it works”When using objectEvents:
- It takes a target function that returns the object to attach events to
- Event handlers are registered using
Renderer2 - Event cleanup is handled automatically through
DestroyRef - Returns an array of cleanup functions if manual cleanup is needed
Example: GLTF Model with Events
Section titled “Example: GLTF Model with Events”@Component({ selector: 'app-astronaut', template: ` @if (gltf.value(); as gltf) { <ngt-group #model [parameters]="options()"> <ngt-mesh receiveShadow castShadow [geometry]="gltf.nodes.Astronaut_mesh.geometry" [material]="gltf.materials.Astronaut_mat" /> </ngt-group> } `, hostDirectives: [{ directive: NgtObjectEvents, outputs: ['click', 'pointerover', 'pointerout'] }]})export class Astronaut { modelRef = viewChild<ElementRef<Group>>('model');
constructor() { const objectEvents = inject(NgtObjectEvents, { host: true }); effect(() => { const model = this.modelRef()?.nativeElement; if (!model) return; objectEvents.ngtObjectEvents.set(model); }); }}Now consumers can use the Astronaut component with event handling
<app-astronaut (click)="onAstronautClick($event)" (pointerover)="onAstronautHover($event)"/>