NgtsBillboard
import { ChangeDetectionStrategy, Component, ElementRef, inject, signal } from '@angular/core';import { SobaWrapper } from '@soba/wrapper.ts';import { TweakpaneCheckbox, TweakpanePane } from 'angular-three-tweakpane';import { NgtCanvas, provideNgtRenderer } from 'angular-three/dom';import { SceneGraph } from './scene-graph';
@Component({ selector: 'app-soba-billboard', template: ` <ngt-canvas [camera]="{ position: [0, 5, 10] }"> <app-soba-wrapper *canvasContent [controls]="null"> <app-scene-graph [follow]="follow()" [lockX]="lockX()" [lockY]="lockY()" [lockZ]="lockZ()" /> </app-soba-wrapper> </ngt-canvas>
<tweakpane-pane title="Billboard" [container]="host"> <tweakpane-checkbox [(value)]="follow" label="Follow" /> <tweakpane-checkbox [(value)]="lockX" label="Lock X" /> <tweakpane-checkbox [(value)]="lockY" label="Lock Y" /> <tweakpane-checkbox [(value)]="lockZ" label="Lock Z" /> </tweakpane-pane> `, host: { class: 'billboard-demo relative block h-full' }, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgtCanvas, SobaWrapper, SceneGraph, TweakpanePane, TweakpaneCheckbox],})export default class Billboard { static clientProviders = [provideNgtRenderer()];
protected host = inject(ElementRef);
protected follow = signal(true); protected lockX = signal(false); protected lockY = signal(false); protected lockZ = signal(false);}import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input } from '@angular/core';import { NgtsBillboard, NgtsText } from 'angular-three-soba/abstractions';import { NgtsOrbitControls } from 'angular-three-soba/controls';
@Component({ selector: 'app-scene-graph', template: ` <ngts-billboard [options]="{ follow: follow(), lockZ: lockZ(), lockY: lockY(), lockX: lockX(), position: [0.5, 2.05, 0.5] }" > <ngts-text text="hello" [options]="{ fontSize: 1, outlineWidth: '5%', outlineColor: '#000000', outlineOpacity: 1 }" /> </ngts-billboard> <ngt-mesh [position]="[0.5, 1, 0.5]"> <ngt-box-geometry /> <ngt-mesh-standard-material color="red" /> </ngt-mesh> <ngt-group [position]="[-2.5, -3, -1]"> <ngts-billboard [options]="{ follow: follow(), lockZ: lockZ(), lockY: lockY(), lockX: lockX(), position: [0, 1.05, 0] }" > <ngts-text text="cone" [options]="{ fontSize: 1, outlineWidth: '5%', outlineColor: '#000000', outlineOpacity: 1 }" /> </ngts-billboard> <ngt-mesh> <ngt-cone-geometry /> <ngt-mesh-standard-material color="green" /> </ngt-mesh> </ngt-group>
<ngts-billboard [options]="{ follow: follow(), lockZ: lockZ(), lockY: lockY(), lockX: lockX(), position: [0, 0, -5] }" > <ngt-mesh> <ngt-plane-geometry /> <ngt-mesh-standard-material color="#000066" /> </ngt-mesh> </ngts-billboard>
<ngts-orbit-controls [options]="{ enablePan: false, zoomSpeed: 0.5 }" /> `, changeDetection: ChangeDetectionStrategy.OnPush, schemas: [CUSTOM_ELEMENTS_SCHEMA], imports: [NgtsBillboard, NgtsText, NgtsOrbitControls],})export class SceneGraph { follow = input(true); lockX = input(false); lockY = input(false); lockZ = input(false);}A component that rotates its contents to always face the camera (billboarding effect). Useful for sprites, labels, or any content that should always face the viewer.
Options
options input accepts any properties from THREE.Group in addition to the following:
Properties
| name | type | description |
|---|---|---|
| follow | boolean | Whether the billboard should follow (face) the camera. Default true. |
| lockX | boolean | Lock rotation on the X axis, preventing the billboard from rotating around X. Default false. |
| lockY | boolean | Lock rotation on the Y axis, preventing the billboard from rotating around Y. Default false. |
| lockZ | boolean | Lock rotation on the Z axis, preventing the billboard from rotating around Z. Default false. |