1
1
import { Canvas } from '@react-three/fiber' ;
2
- import { ComponentProps , ReactNode , useState } from 'react' ;
2
+ import { ComponentProps , ReactNode , useRef , useState } from 'react' ;
3
3
import styled from 'styled-components' ;
4
+ import { OrbitControls as OrbitControlsImpl } from 'three-stdlib' ;
5
+ import { OrbitControls } from '@react-three/drei' ;
4
6
import { useAppSelector } from 'hooks/redux' ;
5
7
import { selectCurrentStyle } from 'features/styles/stylesSlice' ;
6
8
import TakeScreenshot from './three/TakeScreenshot' ;
7
- import CameraManager , { SupportedCameras } from './three/CameraManager' ;
9
+ import CameraManager from './three/CameraManager' ;
8
10
9
11
const ViewStyles = styled . div < { textColor : string } > `
10
12
position: relative;
11
13
min-width: 0;
12
14
min-height: 0;
13
15
14
- .label {
16
+ .overlay {
15
17
position: absolute;
16
- left: 50%;
17
- transform: translateX(-50%);
18
18
color: ${ props => props . textColor } ;
19
+ opacity: 0.17;
19
20
z-index: 100;
21
+
22
+ &:hover {
23
+ opacity: 0.67;
24
+ }
25
+ }
26
+
27
+ .label {
28
+ left: 50%;
29
+ transform: translateX(-50%);
20
30
}
21
31
22
32
.actions {
23
33
display: flex;
24
34
flex-direction: column;
25
- position: absolute;
26
35
right: 0;
27
- opacity: 0.17;
28
- z-index: 100;
29
-
30
- &:hover {
31
- opacity: 0.67;
32
- }
33
36
}
34
37
` ;
35
38
@@ -45,12 +48,12 @@ const onCreated: CanvasProp<'onCreated'> = state => {
45
48
46
49
interface Props {
47
50
label : string ;
48
- camera : SupportedCameras ;
51
+ controlsProps ?: ComponentProps < typeof OrbitControls > ;
49
52
className ?: string ;
50
53
children ?: ReactNode ;
51
54
}
52
55
53
- function GenericView ( { label, camera , className, children } : Props ) : JSX . Element {
56
+ function GenericView ( { label, controlsProps , className, children } : Props ) : JSX . Element {
54
57
const [ screenshot , setScreenshot ] = useState ( {
55
58
requested : false ,
56
59
variant : '' as ComponentProps < typeof TakeScreenshot > [ 'variant' ] ,
@@ -60,28 +63,22 @@ function GenericView({ label, camera, className, children }: Props): JSX.Element
60
63
const requestSVGScreenshot = ( ) => setScreenshot ( { requested : true , variant : 'svg' } ) ;
61
64
const screenshotTaken = ( ) => setScreenshot ( prevState => ( { ...prevState , requested : false } ) ) ;
62
65
63
- const [ cameraAction , setCameraAction ] = useState ( {
64
- reset : false ,
65
- } ) ;
66
-
67
- const requestCameraReset = ( ) => setCameraAction ( { reset : true } ) ;
68
- const cameraReset = ( ) => setCameraAction ( { reset : false } ) ;
69
-
70
66
const style = useAppSelector ( selectCurrentStyle ) ;
71
67
68
+ const cameraControlsRef = useRef < HTMLDivElement | null > ( null ) ;
69
+ const orbitControlsRef = useRef < OrbitControlsImpl | null > ( null ) ;
70
+
72
71
return (
73
72
< ViewStyles className = { className } textColor = { style . overlayColor } >
74
- < span className = "label" > { label } </ span >
75
- < div className = "actions" >
73
+ < div className = "overlay camera" ref = { cameraControlsRef } />
74
+ < span className = "overlay label" > { label } </ span >
75
+ < div className = "overlay actions" >
76
76
< button type = "button" onClick = { requestPNGScreenshot } >
77
77
Save as PNG
78
78
</ button >
79
79
< button type = "button" onClick = { requestSVGScreenshot } >
80
80
Save as SVG
81
81
</ button >
82
- < button type = "button" onClick = { requestCameraReset } >
83
- Reset camera
84
- </ button >
85
82
</ div >
86
83
< Canvas frameloop = "demand" gl = { rendererProps } onCreated = { onCreated } >
87
84
< color attach = "background" args = { [ style . clearColor ] } />
@@ -91,11 +88,14 @@ function GenericView({ label, camera, className, children }: Props): JSX.Element
91
88
label = { label }
92
89
done = { screenshotTaken }
93
90
/>
94
- < CameraManager
95
- defaultCamera = { camera }
96
- resetRequested = { cameraAction . reset }
97
- resetDone = { cameraReset }
98
- />
91
+ { cameraControlsRef . current && orbitControlsRef . current && (
92
+ < CameraManager
93
+ cameraControlsContainer = { cameraControlsRef . current }
94
+ orbitControls = { orbitControlsRef . current }
95
+ />
96
+ ) }
97
+ { /* eslint-disable-next-line react/jsx-props-no-spreading */ }
98
+ < OrbitControls ref = { orbitControlsRef } { ...controlsProps } />
99
99
{ children }
100
100
</ Canvas >
101
101
</ ViewStyles >
0 commit comments