NgtpShockWave
import { ChangeDetectionStrategy, Component } from '@angular/core';import { PostprocessingWrapper } from '@postprocessing/wrapper.ts';import { NgtCanvas, provideNgtRenderer } from 'angular-three/dom';import { SceneGraph } from './scene-graph';
@Component({ selector: 'app-shock-wave', template: ` <ngt-canvas [camera]="{ position: [0, 0, 5], fov: 50 }"> <app-postprocessing-wrapper *canvasContent> <app-scene-graph /> </app-postprocessing-wrapper> </ngt-canvas> `, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'shock-wave-demo relative block h-full' }, imports: [NgtCanvas, PostprocessingWrapper, SceneGraph],})export default class ShockWave { static clientProviders = [provideNgtRenderer()];}import { afterNextRender, ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, viewChild,} from '@angular/core';import { beforeRender, NgtArgs } from 'angular-three';import { NgtpEffectComposer, NgtpShockWave } from 'angular-three-postprocessing';import * as THREE from 'three';
@Component({ selector: 'app-scene-graph', template: ` <!-- Click the sphere to trigger shock wave --> <ngt-mesh #sphere (click)="triggerShockwave()" [position]="[0, 0, 0]"> <ngt-sphere-geometry *args="[0.5, 32, 32]" /> <ngt-mesh-standard-material color="#f97316" [emissive]="'#f97316'" [emissiveIntensity]="0.3" /> </ngt-mesh>
<!-- Background objects to show distortion --> <ngt-mesh [position]="[-2, 1, -2]"> <ngt-box-geometry *args="[0.8, 0.8, 0.8]" /> <ngt-mesh-standard-material color="#3b82f6" /> </ngt-mesh>
<ngt-mesh [position]="[2, -0.5, -1]"> <ngt-torus-geometry *args="[0.4, 0.15, 16, 32]" /> <ngt-mesh-standard-material color="#22c55e" /> </ngt-mesh>
<ngt-mesh [position]="[-1.5, -1, -1.5]"> <ngt-dodecahedron-geometry *args="[0.5, 0]" /> <ngt-mesh-standard-material color="#a855f7" /> </ngt-mesh>
<ngt-mesh [position]="[1.5, 1.2, -2]"> <ngt-octahedron-geometry *args="[0.4, 0]" /> <ngt-mesh-standard-material color="#ec4899" /> </ngt-mesh>
<!-- Grid background --> <ngt-grid-helper *args="[20, 20, '#333', '#333']" [position]="[0, -2, 0]" />
<ngtp-effect-composer> <ngtp-shock-wave #shockwave [options]="{ speed: 1.5, maxRadius: 3, waveSize: 0.4, amplitude: 0.1, }" /> </ngtp-effect-composer> `, schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgtArgs, NgtpEffectComposer, NgtpShockWave],})export class SceneGraph { private sphereRef = viewChild.required<ElementRef<THREE.Mesh>>('sphere'); private shockwaveRef = viewChild.required(NgtpShockWave);
constructor() { beforeRender(({ clock }) => { const t = clock.getElapsedTime(); const sphere = this.sphereRef().nativeElement; // Gentle floating animation sphere.position.y = Math.sin(t * 1.5) * 0.1; sphere.rotation.y = t * 0.5; });
// Auto-trigger shockwave every 3 seconds for demo purposes afterNextRender(() => { // Initial trigger after a short delay setTimeout(() => this.triggerShockwave(), 500); // Then repeat every 3 seconds setInterval(() => this.triggerShockwave(), 3000); }); }
triggerShockwave() { const shockWaveEffect = this.shockwaveRef().effectRef()?.nativeElement; if (!shockWaveEffect) return; shockWaveEffect.explode(); }}The shock wave effect creates an expanding ring of distortion, simulating the visual impact of an explosion or energy pulse.
import { NgtpEffectComposer, NgtpShockWave } from 'angular-three-postprocessing';
@Component({ template: ` <ngtp-effect-composer> <ngtp-shock-wave [options]="{ speed: 2, maxRadius: 1, waveSize: 0.2, amplitude: 0.05 }" /> </ngtp-effect-composer> `, imports: [NgtpEffectComposer, NgtpShockWave],})export class SceneGraph {}Options
Section titled “Options”| Property | Type | Default | Description |
|---|---|---|---|
speed | number | 2.0 | Expansion speed of the wave |
maxRadius | number | 1.0 | Maximum radius before reset |
waveSize | number | 0.2 | Thickness of the wave ring |
amplitude | number | 0.05 | Distortion strength |
Example: Explosion Effect
Section titled “Example: Explosion Effect”import { viewChild, ElementRef } from '@angular/core';import { ShockWaveEffect } from 'postprocessing';
@Component({ template: ` <ngt-mesh (click)="triggerShockwave()" [position]="[0, 0, 0]"> <ngt-sphere-geometry *args="[0.5, 32, 32]" /> <ngt-mesh-standard-material color="orange" /> </ngt-mesh>
<ngtp-effect-composer> <ngtp-shock-wave #shockwave [options]="{ speed: 3, maxRadius: 2, waveSize: 0.3, amplitude: 0.1 }" /> </ngtp-effect-composer> `, imports: [NgtpEffectComposer, NgtpShockWave, NgtArgs], schemas: [CUSTOM_ELEMENTS_SCHEMA],})export class SceneGraph { shockwave = viewChild<ElementRef<ShockWaveEffect>>('shockwave');
triggerShockwave() { const effect = this.shockwave()?.nativeElement; if (effect) { // Reset the effect to trigger a new wave effect.explode(); } }}Example: Continuous Waves
Section titled “Example: Continuous Waves”@Component({ template: ` <ngt-mesh> <ngt-box-geometry /> <ngt-mesh-standard-material color="steelblue" /> </ngt-mesh>
<ngtp-effect-composer> <!-- Slow, subtle continuous wave --> <ngtp-shock-wave [options]="{ speed: 0.5, maxRadius: 3, waveSize: 0.5, amplitude: 0.02 }" /> </ngtp-effect-composer> `, imports: [NgtpEffectComposer, NgtpShockWave], schemas: [CUSTOM_ELEMENTS_SCHEMA],})export class SceneGraph {}- Call
effect.explode()to trigger a new shock wave - The wave automatically resets when it reaches
maxRadius - Higher
amplitudecreates more visible distortion - Smaller
waveSizecreates a sharper, more defined ring - Combine with bloom for glowing energy wave effects
- Use with particle systems for complete explosion visuals