1
1
import {
2
2
ChangeDetectionStrategy ,
3
3
Component ,
4
- ComponentRef ,
5
- DestroyRef ,
6
- ElementRef ,
7
- EnvironmentInjector ,
8
- Injector ,
9
- NgZone ,
10
- Type ,
11
- ViewContainerRef ,
12
4
afterNextRender ,
13
- booleanAttribute ,
14
- computed ,
15
5
createEnvironmentInjector ,
16
- inject ,
17
- input ,
18
- output ,
19
6
signal ,
20
7
untracked ,
21
- viewChild ,
22
8
} from '@angular/core' ;
23
- import { outputFromObservable } from '@angular/core/rxjs-interop' ;
24
- import { injectAutoEffect } from 'ngxtension/auto-effect' ;
25
9
import { NgxResize , ResizeOptions , ResizeResult , provideResizeOptions } from 'ngxtension/resize' ;
26
- import {
27
- Camera ,
28
- OrthographicCamera ,
29
- PerspectiveCamera ,
30
- Raycaster ,
31
- Scene ,
32
- Vector3 ,
33
- WebGLRenderer ,
34
- WebGLRendererParameters ,
35
- WebGLShadowMap ,
36
- } from 'three' ;
37
- import { createPointerEvents } from './dom/events' ;
38
- import { NgtCamera , NgtDomEvent , NgtEventManager } from './events' ;
10
+ import { NgtCanvasHandler } from './canvas-handler' ;
11
+ import { NgtDomEvent } from './events' ;
39
12
import { provideNgtRenderer } from './renderer' ;
40
- import { NgtCanvasConfigurator , NgtCanvasElement , injectCanvasRootInitializer } from './roots' ;
41
- import { NgtRoutedScene } from './routed-scene' ;
42
- import { NgtDpr , NgtPerformance , NgtRendererLike , NgtSize , NgtState , injectStore , provideStore } from './store' ;
43
- import { NgtObject3DNode } from './three-types' ;
44
- import { NgtProperties } from './types' ;
13
+ import { provideStore } from './store' ;
45
14
import { is } from './utils/is' ;
46
- import { NgtSignalStore } from './utils/signal-store' ;
47
-
48
- export type NgtGLOptions =
49
- | NgtRendererLike
50
- | ( ( canvas : NgtCanvasElement ) => NgtRendererLike )
51
- | Partial < NgtProperties < WebGLRenderer > | WebGLRendererParameters >
52
- | undefined ;
53
-
54
- export interface NgtCanvasOptions {
55
- /** A threejs renderer instance or props that go into the default renderer */
56
- gl ?: NgtGLOptions ;
57
- /** Dimensions to fit the renderer to. Will measure canvas dimensions if omitted */
58
- size ?: NgtSize ;
59
- /**
60
- * Enables shadows (by default PCFsoft). Can accept `gl.shadowMap` options for fine-tuning,
61
- * but also strings: 'basic' | 'percentage' | 'soft' | 'variance'.
62
- * @see https://threejs.org/docs/#api/en/renderers/WebGLRenderer.shadowMap
63
- */
64
- shadows ?: boolean | 'basic' | 'percentage' | 'soft' | 'variance' | Partial < WebGLShadowMap > ;
65
- /**
66
- * Disables three r139 color management.
67
- * @see https://threejs.org/docs/#manual/en/introduction/Color-management
68
- */
69
- legacy ?: boolean ;
70
- /** Switch off automatic sRGB color space and gamma correction */
71
- linear ?: boolean ;
72
- /** Use `THREE.NoToneMapping` instead of `THREE.ACESFilmicToneMapping` */
73
- flat ?: boolean ;
74
- /** Creates an orthographic camera */
75
- orthographic ?: boolean ;
76
- /**
77
- * R3F's render mode. Set to `demand` to only render on state change or `never` to take control.
78
- * @see https://docs.pmnd.rs/react-three-fiber/advanced/scaling-performance#on-demand-rendering
79
- */
80
- frameloop ?: 'always' | 'demand' | 'never' ;
81
- /**
82
- * R3F performance options for adaptive performance.
83
- * @see https://docs.pmnd.rs/react-three-fiber/advanced/scaling-performance#movement-regression
84
- */
85
- performance ?: Partial < Omit < NgtPerformance , 'regress' > > ;
86
- /** Target pixel ratio. Can clamp between a range: `[min, max]` */
87
- dpr ?: NgtDpr ;
88
- /** Props that go into the default raycaster */
89
- raycaster ?: Partial < Raycaster > ;
90
- /** A `Scene` instance or props that go into the default scene */
91
- scene ?: Scene | Partial < Scene > ;
92
- /** A `Camera` instance or props that go into the default camera */
93
- camera ?: (
94
- | NgtCamera
95
- | Partial <
96
- NgtObject3DNode < Camera , typeof Camera > &
97
- NgtObject3DNode < PerspectiveCamera , typeof PerspectiveCamera > &
98
- NgtObject3DNode < OrthographicCamera , typeof OrthographicCamera >
99
- >
100
- ) & {
101
- /** Flags the camera as manual, putting projection into your own hands */
102
- manual ?: boolean ;
103
- } ;
104
- /** An R3F event manager to manage elements' pointer events */
105
- events ?: ( store : NgtSignalStore < NgtState > ) => NgtEventManager < HTMLElement > ;
106
- /** The target where events are being subscribed to, default: the div that wraps canvas */
107
- eventSource ?: HTMLElement | ElementRef < HTMLElement > ;
108
- /** The event prefix that is cast into canvas pointer x/y events, default: "offset" */
109
- eventPrefix ?: 'offset' | 'client' | 'page' | 'layer' | 'screen' ;
110
- /** Default coordinate for the camera to look at */
111
- lookAt ?: Vector3 | Parameters < Vector3 [ 'set' ] > ;
112
- }
113
15
114
16
@Component ( {
115
17
selector : 'ngt-canvas' ,
@@ -134,72 +36,18 @@ export interface NgtCanvasOptions {
134
36
} ,
135
37
changeDetection : ChangeDetectionStrategy . OnPush ,
136
38
} )
137
- export class NgtCanvas {
138
- private store = injectStore ( ) ;
139
- private initRoot = injectCanvasRootInitializer ( ) ;
140
- private autoEffect = injectAutoEffect ( ) ;
141
-
142
- private host = inject < ElementRef < HTMLElement > > ( ElementRef ) ;
143
- private viewContainerRef = inject ( ViewContainerRef ) ;
144
- private zone = inject ( NgZone ) ;
145
- private environmentInjector = inject ( EnvironmentInjector ) ;
146
- private injector = inject ( Injector ) ;
147
-
148
- sceneGraph = input . required < Type < any > , Type < any > | 'routed' > ( {
149
- transform : ( value ) => {
150
- if ( value === 'routed' ) return NgtRoutedScene ;
151
- return value ;
152
- } ,
153
- } ) ;
154
- gl = input < NgtGLOptions > ( ) ;
155
- size = input < NgtSize > ( ) ;
156
- shadows = input ( false , {
157
- transform : ( value ) => {
158
- if ( value === '' ) return booleanAttribute ( value ) ;
159
- return value as NonNullable < NgtCanvasOptions [ 'shadows' ] > ;
160
- } ,
161
- } ) ;
162
- legacy = input ( false , { transform : booleanAttribute } ) ;
163
- linear = input ( false , { transform : booleanAttribute } ) ;
164
- flat = input ( false , { transform : booleanAttribute } ) ;
165
- orthographic = input ( false , { transform : booleanAttribute } ) ;
166
- frameloop = input < NonNullable < NgtCanvasOptions [ 'frameloop' ] > > ( 'always' ) ;
167
- performance = input < Partial < Omit < NgtPerformance , 'regress' > > > ( ) ;
168
- dpr = input < NgtDpr > ( [ 1 , 2 ] ) ;
169
- raycaster = input < Partial < Raycaster > > ( ) ;
170
- scene = input < Scene | Partial < Scene > > ( ) ;
171
- camera = input < NonNullable < NgtCanvasOptions [ 'camera' ] > > ( ) ;
172
- events = input ( createPointerEvents ) ;
173
- eventSource = input < HTMLElement | ElementRef < HTMLElement > > ( ) ;
174
- eventPrefix = input < NonNullable < NgtCanvasOptions [ 'eventPrefix' ] > > ( 'offset' ) ;
175
- lookAt = input < Vector3 | Parameters < Vector3 [ 'set' ] > > ( ) ;
176
- created = output < NgtState > ( ) ;
177
- pointerMissed = outputFromObservable ( this . store . get ( 'pointerMissed$' ) ) ;
178
-
179
- glCanvas = viewChild . required < ElementRef < HTMLCanvasElement > > ( 'glCanvas' ) ;
180
- glCanvasViewContainerRef = viewChild . required ( 'glCanvas' , { read : ViewContainerRef } ) ;
181
-
39
+ export class NgtCanvas extends NgtCanvasHandler {
182
40
// NOTE: this signal is updated outside of Zone
183
41
protected resizeResult = signal < ResizeResult > ( { } as ResizeResult , { equal : Object . is } ) ;
184
- protected hbPointerEvents = computed ( ( ) => ( this . eventSource ( ) ? 'none' : 'auto' ) ) ;
185
-
186
- private configurator ?: NgtCanvasConfigurator ;
187
- private glEnvironmentInjector ?: EnvironmentInjector ;
188
- private glRef ?: ComponentRef < unknown > ;
189
42
190
43
constructor ( ) {
44
+ super ( ) ;
191
45
afterNextRender ( ( ) => {
192
46
this . zone . runOutsideAngular ( ( ) => {
193
47
this . configurator = this . initRoot ( this . glCanvas ( ) . nativeElement ) ;
194
48
this . noZoneResizeEffect ( ) ;
195
49
} ) ;
196
50
} ) ;
197
-
198
- inject ( DestroyRef ) . onDestroy ( ( ) => {
199
- this . glRef ?. destroy ( ) ;
200
- this . glEnvironmentInjector ?. destroy ( ) ;
201
- this . configurator ?. destroy ( ) ;
202
- } ) ;
203
51
}
204
52
205
53
private noZoneResizeEffect ( ) {
0 commit comments