1
- import React , {
2
- useState ,
3
- useEffect ,
4
- useImperativeHandle ,
5
- forwardRef ,
6
- createRef ,
7
- Ref ,
8
- useRef
9
- } from "react"
1
+ import React , { useState , useEffect , useImperativeHandle , forwardRef , useRef , useCallback , useMemo } from "react"
10
2
import {
11
3
Viewer ,
12
4
ViewerConfig ,
@@ -75,8 +67,8 @@ const omittedProps = [
75
67
"onDblclick" ,
76
68
"onReady" ,
77
69
]
78
-
79
- export interface Props extends ViewerConfig {
70
+ type MakeOptional < T , K extends keyof T > = Omit < T , K > & Partial < Pick < T , K > > ;
71
+ export interface Props extends MakeOptional < ViewerConfig , "container" > {
80
72
src : string ;
81
73
navbar ?: boolean | string | Array < string | NavbarCustomButton > ;
82
74
height : string ;
@@ -140,8 +132,92 @@ function filterNavbar(navbar?: boolean | string | Array<string | NavbarCustomBut
140
132
return navbar
141
133
}
142
134
143
- const ReactPhotoSphereViewer = forwardRef ( ( options : Props , ref : unknown ) : React . ReactElement => {
144
- const sphereElementRef = createRef < HTMLDivElement > ( )
135
+ function useDomElement ( ) : [ HTMLDivElement | undefined , ( r : HTMLDivElement ) => void ] {
136
+ const [ element , setElement ] = useState < HTMLDivElement > ( )
137
+ const ref = useCallback (
138
+ ( r : HTMLDivElement ) => {
139
+ if ( r && r !== element ) {
140
+ setElement ( r )
141
+ }
142
+ } ,
143
+ [ element ]
144
+ )
145
+ return [ element , ref ]
146
+ }
147
+
148
+ export interface ViewerAPI {
149
+ animate ( options : AnimateOptions ) : void ;
150
+ destroy ( ) : void ;
151
+ rotate ( options : { x : number ; y : number } ) : void ;
152
+ setOption ( option : keyof ViewerConfig , value : unknown ) : void ;
153
+ setOptions ( options : ViewerConfig ) : void ;
154
+ getCurrentNavbar ( ) : ( string | object ) [ ] | void ;
155
+ zoom ( value : number ) : void ;
156
+ zoomIn ( ) : void ;
157
+ zoomOut ( ) : void ;
158
+ resize ( size : CssSize ) : void ;
159
+ enterFullscreen ( ) : void ;
160
+ exitFullscreen ( ) : void ;
161
+ toggleFullscreen ( ) : void ;
162
+ isFullscreenEnabled ( ) : boolean | void ;
163
+ startAutoRotate ( ) : void ;
164
+ stopAutoRotate ( ) : void ;
165
+ getPlugin ( pluginName : string ) : unknown | void ;
166
+ getPosition ( ) : unknown | void ; // Specify the return type
167
+ getZoomLevel ( ) : unknown | void ; // Specify the return type
168
+ getSize ( ) : unknown | void ; // Specify the return type
169
+ needsUpdate ( ) : boolean | void ;
170
+ autoSize ( ) : void ;
171
+ setPanorama ( path : string , options ?: object ) : void ;
172
+ setOverlay ( path : string , opacity ?: number ) : void ;
173
+ toggleAutorotate ( ) : void ;
174
+ showError ( message : string ) : void ;
175
+ hideError ( ) : void ;
176
+ startKeyboardControl ( ) : void ;
177
+ stopKeyboardControl ( ) : void ;
178
+ }
179
+
180
+ const ReactPhotoSphereViewer = forwardRef < ViewerAPI , Props > ( ( props , ref ) : React . ReactElement => {
181
+ const [ sphereElement , setRef ] = useDomElement ( )
182
+ const options = useMemo (
183
+ ( ) => props ,
184
+ [
185
+ // recreate options when individual props change
186
+ props . src ,
187
+ props . navbar ,
188
+ props . height ,
189
+ props . width ,
190
+ props . containerClass ,
191
+ props . littlePlanet ,
192
+ props . fishEye ,
193
+ props . lang ,
194
+ props . onPositionChange ,
195
+ props . onZoomChange ,
196
+ props . onClick ,
197
+ props . onDblclick ,
198
+ props . onReady ,
199
+ props . moveSpeed ,
200
+ props . zoomSpeed ,
201
+ props . moveInertia ,
202
+ props . mousewheel ,
203
+ props . mousemove ,
204
+ props . mousewheelCtrlKey ,
205
+ props . touchmoveTwoFingers ,
206
+ props . useXmpData ,
207
+ props . panoData ,
208
+ props . requestHeaders ,
209
+ props . canvasBackground ,
210
+ props . withCredentials ,
211
+ props . keyboard ,
212
+ props . plugins ,
213
+ props . sphereCorrection ,
214
+ props . minFov ,
215
+ props . maxFov ,
216
+ props . defaultZoomLvl ,
217
+ props . defaultYaw ,
218
+ props . defaultPitch ,
219
+ ]
220
+ )
145
221
const spherePlayerInstance = useRef < Viewer | null > ( null )
146
222
let LITTLEPLANET_MAX_ZOOM = 130
147
223
const [ LITTLEPLANET_DEF_LAT ] = useState ( - 90 )
@@ -164,10 +240,10 @@ const ReactPhotoSphereViewer = forwardRef((options: Props, ref: unknown): React.
164
240
165
241
useEffect ( ( ) => {
166
242
let littlePlanetEnabled = true
167
- if ( sphereElementRef . current && ! spherePlayerInstance . current ) {
243
+ if ( sphereElement && ! spherePlayerInstance . current ) {
168
244
const _c = new Viewer ( {
169
245
...adaptOptions ( options ) ,
170
- container : sphereElementRef . current ,
246
+ container : sphereElement ,
171
247
panorama : options . src ,
172
248
size : {
173
249
height : options . height ,
@@ -318,10 +394,15 @@ const ReactPhotoSphereViewer = forwardRef((options: Props, ref: unknown): React.
318
394
319
395
spherePlayerInstance . current = _c
320
396
}
321
- } , [ sphereElementRef , options ] )
397
+ } , [ sphereElement , options ] )
322
398
323
- // Methods
324
- useImperativeHandle ( ref as Ref < unknown > , ( ) => ( {
399
+ useEffect ( ( ) => {
400
+ if ( spherePlayerInstance . current ) {
401
+ spherePlayerInstance . current . setPanorama ( options . src , options )
402
+ }
403
+ } , [ options . src ] )
404
+
405
+ const _imperativeHandle = ( ) => ( {
325
406
animate ( options : AnimateOptions ) {
326
407
Emitter . emit ( "animate" , options )
327
408
} ,
@@ -408,12 +489,17 @@ const ReactPhotoSphereViewer = forwardRef((options: Props, ref: unknown): React.
408
489
} ,
409
490
stopKeyboardControl ( ) {
410
491
return spherePlayerInstance . current ?. stopKeyboardControl ( )
411
- }
412
- } ) , [ spherePlayerInstance . current , sphereElementRef , options , ref ] )
492
+ } ,
493
+ } )
494
+ // Methods
495
+ useImperativeHandle ( ref , _imperativeHandle , [
496
+ spherePlayerInstance . current ,
497
+ sphereElement ,
498
+ options ,
499
+ ref ,
500
+ ] )
413
501
414
- return (
415
- < div className = { options . containerClass || "view-container" } ref = { sphereElementRef } />
416
- )
502
+ return < div className = { options . containerClass || "view-container" } ref = { setRef } />
417
503
} )
418
504
419
505
export {
0 commit comments