Skip to content

How it works

Import NgtcPhysics from angular-three-cannon

1
import { NgtcPhysics } from 'angular-three-cannon';

Render the NgtcPhysics component in your scene graph

1
@Component({
2
standalone: true,
3
imports: [NgtcPhysics],
4
template: `
5
<ngtc-physics>
6
<!-- objects that are subject to physics -->
7
</ngtc-physics>
8
`,
9
schemas: [CUSTOM_ELEMENTS_SCHEMA],
10
})
11
export class SceneGraph {}

Pick a Body shape

angular-three-cannon/body provides a variety of body shapes in form of Custom Inject Function that can be used to create physics bodies.

1
import { injectBox } from 'angular-three-cannon/body';
2
3
@Component({
4
selector: 'app-box',
5
standalone: true,
6
template: `
7
<ngt-mesh #mesh [receiveShadow]="true" [castShadow]="true">
8
<ngt-box-geometry />
9
</ngt-mesh>
10
`,
11
imports: [NgtArgs],
12
schemas: [CUSTOM_ELEMENTS_SCHEMA],
13
changeDetection: ChangeDetectionStrategy.OnPush,
14
})
15
export class Box {
16
mesh = viewChild.required<ElementRef<Mesh>>('mesh');
17
box = injectBox(() => ({ mass: 1 }), this.mesh);
18
}

injectBox accepts some physics properties as an argument and an () => ElementRef<Object3D> as the second argument to tie the body to the object.

The returned value is a Signal<NgtcBodyPublicApi | null> that can be used to control the body, set position, rotation, and subscribe to changes.

1
import { injectBox } from 'angular-three-cannon/body';
2
3
@Component({
4
selector: 'app-box',
5
standalone: true,
6
template: `
7
<ngt-mesh #mesh [receiveShadow]="true" [castShadow]="true">
8
<ngt-box-geometry />
9
</ngt-mesh>
10
`,
11
imports: [NgtArgs],
12
schemas: [CUSTOM_ELEMENTS_SCHEMA],
13
changeDetection: ChangeDetectionStrategy.OnPush,
14
})
15
export class Box {
16
mesh = viewChild.required<ElementRef<Mesh>>('mesh');
17
box = injectBox(() => ({ mass: 1 }), this.mesh);
18
19
constructor() {
20
injectBeforeRender(({ clock }) => {
21
const api = this.box();
22
if (!api) return;
23
api.position.set(Math.sin(clock.getElapsedTime()) * 5, 0, 0);
24
})
25
}
26
}

Example