Skip to content

Commit 155a68d

Browse files
committed
refactor(soba): adjust html with new renderer
1 parent b41f1d6 commit 155a68d

File tree

3 files changed

+69
-55
lines changed

3 files changed

+69
-55
lines changed

libs/soba/misc/src/lib/html/html-content.ts

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import {
1212
untracked,
1313
viewChild,
1414
} from '@angular/core';
15-
import { injectBeforeRender, NgtHTML, pick, resolveRef } from 'angular-three';
15+
import { injectBeforeRender, injectStore, is, NgtHTML, pick, resolveRef } from 'angular-three';
1616
import { mergeInputs } from 'ngxtension/inject-inputs';
17-
import { Object3D, OrthographicCamera, Vector3 } from 'three';
17+
import * as THREE from 'three';
1818
import { NgtsHTML } from './html';
1919
import {
2020
CalculatePosition,
@@ -70,7 +70,7 @@ const defaultHtmlContentOptions: NgtsHTMLContentOptions = {
7070
};
7171

7272
@Component({
73-
selector: '[ngtsHTMLContent]',
73+
selector: '[htmlContent]',
7474
template: `
7575
@if (html.transform()) {
7676
<div
@@ -90,10 +90,10 @@ const defaultHtmlContentOptions: NgtsHTMLContentOptions = {
9090
#container
9191
style="position:absolute"
9292
[style.transform]="center() ? 'translate3d(-50%,-50%,0)' : 'none'"
93-
[style.top]="fullscreen() ? -size().height / 2 + 'px' : 'unset'"
94-
[style.left]="fullscreen() ? -size().width / 2 + 'px' : 'unset'"
95-
[style.width]="fullscreen() ? size().width : 'unset'"
96-
[style.height]="fullscreen() ? size().height : 'unset'"
93+
[style.top]="fullscreen() ? -size.height() / 2 + 'px' : 'unset'"
94+
[style.left]="fullscreen() ? -size.width() / 2 + 'px' : 'unset'"
95+
[style.width]="fullscreen() ? size.width() : 'unset'"
96+
[style.height]="fullscreen() ? size.height() : 'unset'"
9797
[class]="containerClass()"
9898
[style]="containerStyle()"
9999
>
@@ -112,21 +112,18 @@ const defaultHtmlContentOptions: NgtsHTMLContentOptions = {
112112
export class NgtsHTMLContent extends NgtHTML {
113113
options = input(defaultHtmlContentOptions, {
114114
transform: mergeInputs(defaultHtmlContentOptions),
115-
alias: 'ngtsHTMLContent',
115+
alias: 'htmlContent',
116116
});
117117
occluded = output<boolean>();
118118

119-
html = inject(NgtsHTML);
120-
121119
transformOuterRef = viewChild<ElementRef<HTMLDivElement>>('transformOuter');
122120
transformInnerRef = viewChild<ElementRef<HTMLDivElement>>('transformInner');
123121
containerRef = viewChild<ElementRef<HTMLDivElement>>('container');
124122

125-
private gl = this.store.select('gl');
126-
private events = this.store.select('events');
127-
private camera = this.store.select('camera');
128-
private scene = this.store.select('scene');
129-
protected size = this.store.select('size');
123+
protected html = inject(NgtsHTML);
124+
private host = inject<ElementRef<HTMLElement>>(ElementRef);
125+
private store = injectStore();
126+
protected size = this.store.size;
130127

131128
private parent = pick(this.options, 'parent');
132129
private zIndexRange = pick(this.options, 'zIndexRange');
@@ -141,7 +138,7 @@ export class NgtsHTMLContent extends NgtHTML {
141138
private target = computed(() => {
142139
const parent = resolveRef(this.parent());
143140
if (parent) return parent;
144-
return (this.events().connected || this.gl().domElement.parentNode) as HTMLElement;
141+
return (this.store.events.connected?.() || this.store.gl.domElement.parentNode()) as HTMLElement;
145142
});
146143

147144
constructor() {
@@ -154,7 +151,7 @@ export class NgtsHTMLContent extends NgtHTML {
154151
effect(() => {
155152
const [occlude, canvasEl, zIndexRange] = [
156153
this.html.occlude(),
157-
untracked(this.gl).domElement,
154+
this.store.snapshot.gl.domElement,
158155
untracked(this.zIndexRange),
159156
];
160157

@@ -175,11 +172,11 @@ export class NgtsHTMLContent extends NgtHTML {
175172
this.target(),
176173
this.host.nativeElement,
177174
untracked(this.prepend),
178-
untracked(this.scene),
175+
this.store.snapshot.scene,
179176
untracked(this.calculatePosition),
180177
untracked(this.html.groupRef).nativeElement,
181-
untracked(this.size),
182-
untracked(this.camera),
178+
this.store.snapshot.size,
179+
this.store.snapshot.camera,
183180
];
184181

185182
scene.updateMatrixWorld();
@@ -254,11 +251,11 @@ export class NgtsHTMLContent extends NgtHTML {
254251
Math.abs(oldPosition[1] - vec[1]) > eps
255252
) {
256253
const isBehindCamera = isObjectBehindCamera(group, camera);
257-
let raytraceTarget: null | undefined | boolean | Object3D[] = false;
254+
let raytraceTarget: null | undefined | boolean | THREE.Object3D[] = false;
258255

259256
if (isRaycastOcclusion) {
260257
if (Array.isArray(occlude)) {
261-
raytraceTarget = occlude.map((item) => resolveRef(item)) as Object3D[];
258+
raytraceTarget = occlude.map((item) => resolveRef(item)) as THREE.Object3D[];
262259
} else if (occlude !== 'blending') {
263260
raytraceTarget = [scene];
264261
}
@@ -289,7 +286,7 @@ export class NgtsHTMLContent extends NgtHTML {
289286
if (transform) {
290287
const [widthHalf, heightHalf] = [size.width / 2, size.height / 2];
291288
const fov = camera.projectionMatrix.elements[5] * heightHalf;
292-
const { isOrthographicCamera, top, left, bottom, right } = camera as OrthographicCamera;
289+
const { isOrthographicCamera, top, left, bottom, right } = camera as THREE.OrthographicCamera;
293290
const cameraMatrix = getCameraCSSMatrix(camera.matrixWorldInverse);
294291
const cameraTransform = isOrthographicCamera
295292
? `scale(${fov})translate(${epsilon(-(right + left) / 2)}px,${epsilon((top + bottom) / 2)}px)`
@@ -332,13 +329,13 @@ export class NgtsHTMLContent extends NgtHTML {
332329
const el = transformOuterEl.children[0];
333330

334331
if (el?.clientWidth && el?.clientHeight) {
335-
const { isOrthographicCamera } = camera as OrthographicCamera;
332+
const { isOrthographicCamera } = camera as THREE.OrthographicCamera;
336333

337334
if (isOrthographicCamera || occlusionGeometry) {
338335
if (scale) {
339336
if (!Array.isArray(scale)) {
340337
occlusionMesh.scale.setScalar(1 / (scale as number));
341-
} else if (scale instanceof Vector3) {
338+
} else if (is.three<THREE.Vector3>(scale, 'isVector3')) {
342339
occlusionMesh.scale.copy(scale.clone().divideScalar(1));
343340
} else {
344341
occlusionMesh.scale.set(1 / scale[0], 1 / scale[1], 1 / scale[2]);

libs/soba/misc/src/lib/html/html.ts

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import {
77
input,
88
viewChild,
99
} from '@angular/core';
10-
import { extend, is, NgtGroup, omit, pick } from 'angular-three';
10+
import { extend, is, NgtThreeElements, omit, pick } from 'angular-three';
1111
import { mergeInputs } from 'ngxtension/inject-inputs';
12-
import { DoubleSide, Group, Mesh, Object3D, PlaneGeometry, ShaderMaterial } from 'three';
12+
import * as THREE from 'three';
13+
import { Group, Mesh, PlaneGeometry, ShaderMaterial } from 'three';
14+
import { NgtsHTMLContent } from './html-content';
1315

14-
export interface NgtsHTMLOptions extends Partial<NgtGroup> {
15-
occlude: ElementRef<Object3D>[] | Object3D[] | boolean | 'raycast' | 'blending';
16+
export interface NgtsHTMLOptions extends Partial<NgtThreeElements['ngt-group']> {
17+
occlude: ElementRef<THREE.Object3D>[] | THREE.Object3D[] | boolean | 'raycast' | 'blending';
1618
transform: boolean;
1719
castShadow: boolean;
1820
receiveShadow: boolean;
@@ -52,17 +54,16 @@ const defaultHtmlOptions: NgtsHTMLOptions = {
5254
})
5355
export class NgtsHTML {
5456
options = input(defaultHtmlOptions, { transform: mergeInputs(defaultHtmlOptions) });
55-
parameters = omit(this.options, ['occlude', 'castShadow', 'receiveShadow', 'transform']);
57+
protected parameters = omit(this.options, ['occlude', 'castShadow', 'receiveShadow', 'transform']);
5658

57-
groupRef = viewChild.required<ElementRef<Group>>('group');
58-
occlusionMeshRef = viewChild<ElementRef<Mesh>>('occlusionMesh');
59-
occlusionGeometryRef = viewChild<ElementRef<PlaneGeometry>>('occlusionGeometry');
59+
groupRef = viewChild.required<ElementRef<THREE.Group>>('group');
60+
occlusionMeshRef = viewChild<ElementRef<THREE.Mesh>>('occlusionMesh');
61+
occlusionGeometryRef = viewChild<ElementRef<THREE.PlaneGeometry>>('occlusionGeometry');
6062

63+
protected castShadow = pick(this.options, 'castShadow');
64+
protected receiveShadow = pick(this.options, 'receiveShadow');
6165
occlude = pick(this.options, 'occlude');
6266
transform = pick(this.options, 'transform');
63-
castShadow = pick(this.options, 'castShadow');
64-
receiveShadow = pick(this.options, 'receiveShadow');
65-
scale = pick(this.options, 'scale');
6667

6768
isRaycastOcclusion = computed(() => {
6869
const occlude = this.occlude();
@@ -117,12 +118,14 @@ export class NgtsHTML {
117118
return { vertexShader, fragmentShader };
118119
});
119120

120-
vertexShader = pick(this.shaders, 'vertexShader');
121-
fragmentShader = pick(this.shaders, 'fragmentShader');
121+
protected vertexShader = pick(this.shaders, 'vertexShader');
122+
protected fragmentShader = pick(this.shaders, 'fragmentShader');
122123

123124
constructor() {
124125
extend({ Group, Mesh, PlaneGeometry, ShaderMaterial });
125126
}
126127

127-
protected readonly DoubleSide = DoubleSide;
128+
protected readonly DoubleSide = THREE.DoubleSide;
128129
}
130+
131+
export const NgtsHTMLDeclarations = [NgtsHTML, NgtsHTMLContent] as const;

libs/soba/misc/src/lib/html/utils.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import { Camera, Matrix4, Object3D, OrthographicCamera, PerspectiveCamera, Raycaster, Vector2, Vector3 } from 'three';
1+
import { is } from 'angular-three';
2+
import * as THREE from 'three';
23

3-
const v1 = new Vector3();
4-
const v2 = new Vector3();
5-
const v3 = new Vector3();
6-
const v4 = new Vector2();
4+
const v1 = new THREE.Vector3();
5+
const v2 = new THREE.Vector3();
6+
const v3 = new THREE.Vector3();
7+
const v4 = new THREE.Vector2();
78

8-
export function defaultCalculatePosition(el: Object3D, camera: Camera, size: { width: number; height: number }) {
9+
export function defaultCalculatePosition(
10+
el: THREE.Object3D,
11+
camera: THREE.Camera,
12+
size: { width: number; height: number },
13+
) {
914
const objectPos = v1.setFromMatrixPosition(el.matrixWorld);
1015
objectPos.project(camera);
1116
const widthHalf = size.width / 2;
@@ -15,15 +20,20 @@ export function defaultCalculatePosition(el: Object3D, camera: Camera, size: { w
1520

1621
export type CalculatePosition = typeof defaultCalculatePosition;
1722

18-
export function isObjectBehindCamera(el: Object3D, camera: Camera) {
23+
export function isObjectBehindCamera(el: THREE.Object3D, camera: THREE.Camera) {
1924
const objectPos = v1.setFromMatrixPosition(el.matrixWorld);
2025
const cameraPos = v2.setFromMatrixPosition(camera.matrixWorld);
2126
const deltaCamObj = objectPos.sub(cameraPos);
2227
const camDir = camera.getWorldDirection(v3);
2328
return deltaCamObj.angleTo(camDir) > Math.PI / 2;
2429
}
2530

26-
export function isObjectVisible(el: Object3D, camera: Camera, raycaster: Raycaster, occlude: Object3D[]) {
31+
export function isObjectVisible(
32+
el: THREE.Object3D,
33+
camera: THREE.Camera,
34+
raycaster: THREE.Raycaster,
35+
occlude: THREE.Object3D[],
36+
) {
2737
const elPos = v1.setFromMatrixPosition(el.matrixWorld);
2838
const screenPos = elPos.clone();
2939
screenPos.project(camera);
@@ -38,9 +48,9 @@ export function isObjectVisible(el: Object3D, camera: Camera, raycaster: Raycast
3848
return true;
3949
}
4050

41-
export function objectScale(el: Object3D, camera: Camera) {
42-
if (camera instanceof OrthographicCamera) return camera.zoom;
43-
if (camera instanceof PerspectiveCamera) {
51+
export function objectScale(el: THREE.Object3D, camera: THREE.Camera) {
52+
if (is.three<THREE.OrthographicCamera>(camera, 'isOrthographicCamera')) return camera.zoom;
53+
if (is.three<THREE.PerspectiveCamera>(camera, 'isPerspectiveCamera')) {
4454
const objectPos = v1.setFromMatrixPosition(el.matrixWorld);
4555
const cameraPos = v2.setFromMatrixPosition(camera.matrixWorld);
4656
const vFOV = (camera.fov * Math.PI) / 180;
@@ -51,8 +61,11 @@ export function objectScale(el: Object3D, camera: Camera) {
5161
return 1;
5262
}
5363

54-
export function objectZIndex(el: Object3D, camera: Camera, zIndexRange: Array<number>) {
55-
if (camera instanceof PerspectiveCamera || camera instanceof OrthographicCamera) {
64+
export function objectZIndex(el: THREE.Object3D, camera: THREE.Camera, zIndexRange: Array<number>) {
65+
if (
66+
is.three<THREE.PerspectiveCamera>(camera, 'isPerspectiveCamera') ||
67+
is.three<THREE.OrthographicCamera>(camera, 'isOrthographicCamera')
68+
) {
5669
const objectPos = v1.setFromMatrixPosition(el.matrixWorld);
5770
const cameraPos = v2.setFromMatrixPosition(camera.matrixWorld);
5871
const dist = objectPos.distanceTo(cameraPos);
@@ -67,7 +80,7 @@ export function epsilon(value: number) {
6780
return Math.abs(value) < 1e-10 ? 0 : value;
6881
}
6982

70-
export function getCSSMatrix(matrix: Matrix4, multipliers: number[], prepend = '') {
83+
export function getCSSMatrix(matrix: THREE.Matrix4, multipliers: number[], prepend = '') {
7184
let matrix3d = 'matrix3d(';
7285
for (let i = 0; i !== 16; i++) {
7386
matrix3d += epsilon(multipliers[i] * matrix.elements[i]) + (i !== 15 ? ',' : ')');
@@ -76,9 +89,10 @@ export function getCSSMatrix(matrix: Matrix4, multipliers: number[], prepend = '
7689
}
7790

7891
export const getCameraCSSMatrix = ((multipliers: number[]) => {
79-
return (matrix: Matrix4) => getCSSMatrix(matrix, multipliers);
92+
return (matrix: THREE.Matrix4) => getCSSMatrix(matrix, multipliers);
8093
})([1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1]);
8194

8295
export const getObjectCSSMatrix = ((scaleMultipliers: (n: number) => number[]) => {
83-
return (matrix: Matrix4, factor: number) => getCSSMatrix(matrix, scaleMultipliers(factor), 'translate(-50%,-50%)');
96+
return (matrix: THREE.Matrix4, factor: number) =>
97+
getCSSMatrix(matrix, scaleMultipliers(factor), 'translate(-50%,-50%)');
8498
})((f: number) => [1 / f, 1 / f, 1 / f, 1, -1 / f, -1 / f, -1 / f, -1, 1 / f, 1 / f, 1 / f, 1, 1, 1, 1, 1]);

0 commit comments

Comments
 (0)