Skip to content

Commit 3db1aeb

Browse files
committed
docs: add view-cube to showcase portal
1 parent cdf0637 commit 3db1aeb

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

apps/demo/src/app/app.routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ import { Routes } from '@angular/router';
33
export const routes: Routes = [
44
{ path: '', redirectTo: 'test', pathMatch: 'full' },
55
{ path: 'test', loadComponent: () => import('./test/test.component') },
6+
{ path: 'view-cube', loadComponent: () => import('./view-cube/view-cube.component') },
67
];
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, inject, ViewChild } from '@angular/core';
2+
import {
3+
extend,
4+
NgtArgs,
5+
NgtCanvas,
6+
NgtPortal,
7+
NgtPortalContent,
8+
NgtPush,
9+
NgtRenderState,
10+
NgtRepeat,
11+
NgtRxStore,
12+
NgtStore,
13+
prepare,
14+
} from 'angular-three';
15+
import * as THREE from 'three';
16+
import { OrbitControls } from 'three-stdlib';
17+
18+
extend({ OrbitControls });
19+
20+
@Component({
21+
selector: 'view-cube',
22+
standalone: true,
23+
template: `
24+
<ngt-portal (beforeRender)="onBeforeRender($event.root)" [state]="{camera}">
25+
<ng-template ngtPortalContent>
26+
<ngt-mesh
27+
#cube
28+
[position]="position"
29+
(pointerout)="hovered = -1"
30+
(pointermove)="hovered = Math.floor(($any($event).faceIndex || 0) / 2)"
31+
>
32+
<ngt-mesh-lambert-material
33+
*ngFor="let i; repeat: 6"
34+
[attach]="['material', i]"
35+
[color]="hovered === i ? 'orange' : 'white'"
36+
/>
37+
<ngt-box-geometry *args="[60, 60, 60]" />
38+
</ngt-mesh>
39+
<ngt-ambient-light [intensity]="1" />
40+
<ngt-point-light [position]="200" [intensity]="0.5" />
41+
</ng-template>
42+
</ngt-portal>
43+
`,
44+
imports: [NgtPortal, NgtPortalContent, NgtPush, NgtArgs, NgtRepeat],
45+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
46+
})
47+
export class ViewCube extends NgtRxStore {
48+
private readonly store = inject(NgtStore);
49+
readonly size = this.store.get('size');
50+
51+
private readonly matrix = new THREE.Matrix4();
52+
53+
readonly position = [this.size.width / 2 - 80, this.size.height / 2 - 80, 0];
54+
readonly Math = Math;
55+
56+
@ViewChild('cube') cube?: ElementRef<THREE.Mesh>;
57+
58+
readonly camera = prepare(() => {
59+
const size = this.size;
60+
const cam = new THREE.OrthographicCamera(size.width / -2, size.width / 2, size.height / 2, size.height / -2);
61+
cam.position.set(0, 0, 100);
62+
return cam;
63+
});
64+
65+
hovered = -1;
66+
67+
onBeforeRender({ camera }: NgtRenderState) {
68+
if (this.cube?.nativeElement) {
69+
this.matrix.copy(camera.matrix).invert();
70+
this.cube.nativeElement.quaternion.setFromRotationMatrix(this.matrix);
71+
}
72+
}
73+
}
74+
75+
@Component({
76+
selector: 'demo-view-cube-scene',
77+
standalone: true,
78+
template: `
79+
<ngt-ambient-light [intensity]="0.5" />
80+
<ngt-mesh [scale]="2">
81+
<ngt-torus-geometry *args="[1, 0.25, 32, 100]" />
82+
<ngt-mesh-normal-material />
83+
</ngt-mesh>
84+
<ngt-orbit-controls *args="[camera, glDom]" [enableDamping]="true" />
85+
<view-cube />
86+
`,
87+
imports: [ViewCube, NgtArgs],
88+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
89+
})
90+
export class Scene {
91+
private readonly store = inject(NgtStore);
92+
readonly camera = this.store.get('camera');
93+
readonly glDom = this.store.get('gl', 'domElement');
94+
}
95+
96+
@Component({
97+
selector: 'demo-view-cube',
98+
standalone: true,
99+
template: ` <ngt-canvas [sceneGraph]="Scene" />`,
100+
imports: [NgtCanvas],
101+
})
102+
export default class SandboxViewCube {
103+
readonly Scene = Scene;
104+
}

0 commit comments

Comments
 (0)