NgtsAdaptiveEvents
import { ChangeDetectionStrategy, Component } from '@angular/core';import { SobaWrapper } from '@soba/wrapper.ts';import { NgtCanvas, provideNgtRenderer } from 'angular-three/dom';import { SceneGraph } from './scene-graph';
@Component({ selector: 'app-adaptive-events', template: ` <ngt-canvas [camera]="{ position: [0, 0, 5], fov: 50 }" [performance]="{ min: 0.2 }"> <app-soba-wrapper *canvasContent [controls]="null"> <app-scene-graph /> </app-soba-wrapper> </ngt-canvas> `, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'adaptive-events-demo relative block h-full' }, imports: [NgtCanvas, SobaWrapper, SceneGraph],})export default class AdaptiveEvents { static clientProviders = [provideNgtRenderer()];}import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, signal } from '@angular/core';import { beforeRender, NgtArgs } from 'angular-three';import { NgtsOrbitControls } from 'angular-three-soba/controls';import { NgtsAdaptiveDpr, NgtsAdaptiveEvents } from 'angular-three-soba/performances';import * as THREE from 'three';
@Component({ selector: 'app-scene-graph', template: ` <!-- Interactive meshes --> @for (pos of positions; track $index) { <ngt-mesh [position]="pos" (pointerover)="hoveredIndex.set($index)" (pointerout)="hoveredIndex.set(-1)"> <ngt-box-geometry *args="[0.5, 0.5, 0.5]" /> <ngt-mesh-standard-material [color]="hoveredIndex() === $index ? '#ff6b6b' : '#4ecdc4'" /> </ngt-mesh> }
<!-- Spinning torus to create load --> <ngt-mesh #torus [position]="[0, 0, -2]"> <ngt-torus-knot-geometry *args="[0.8, 0.3, 256, 64]" /> <ngt-mesh-standard-material color="#a29bfe" /> </ngt-mesh>
<!-- Adaptive performance components --> <ngts-adaptive-dpr [pixelated]="true" /> <ngts-adaptive-events />
<!-- Controls with regress to trigger performance regression --> <ngts-orbit-controls [options]="{ regress: true }" /> `, schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgtArgs, NgtsAdaptiveDpr, NgtsAdaptiveEvents, NgtsOrbitControls],})export class SceneGraph { hoveredIndex = signal(-1);
// Grid of interactive boxes positions = [ [-1.5, 1, 0], [0, 1, 0], [1.5, 1, 0], [-1.5, -0.5, 0], [0, -0.5, 0], [1.5, -0.5, 0], ];
constructor() { // Animate torus to create continuous rendering load let torusMesh: THREE.Mesh | null = null;
beforeRender(({ scene, delta }) => { if (!torusMesh) { torusMesh = scene.getObjectByName('torus') as THREE.Mesh; } // Find torus by traversing - simpler approach scene.traverse((obj) => { if (obj.type === 'Mesh' && (obj as THREE.Mesh).geometry?.type === 'TorusKnotGeometry') { obj.rotation.x += delta * 0.5; obj.rotation.y += delta * 0.3; } }); }); }}NgtsAdaptiveEvents is a port of Drei’s AdaptiveEvents which dynamically toggles event handling based on the canvas’ performance settings. When performance degrades, event handling is disabled to reduce computational overhead.
This is particularly useful when combined with NgtsAdaptiveDpr and controls that support the regress flag (like NgtsOrbitControls).
Usage
import { NgtsAdaptiveEvents } from 'angular-three-soba/performances';<ngts-adaptive-events />Example with Controls
<ngts-adaptive-dpr [pixelated]="true" /><ngts-adaptive-events /><ngts-orbit-controls [options]="{ regress: true }" />When the camera is moving (regress is triggered), events are disabled to improve performance during the interaction.