@@ -19,6 +19,7 @@ export interface IVideoHandle {
1919 toggle : ( ) => void ;
2020 mute : ( m ?: boolean ) => void ;
2121 seek : ( timeSec : number ) => void ;
22+ toggleFullscreen : ( ) => void ;
2223 getEl : ( ) => HTMLVideoElement | null ;
2324}
2425
@@ -78,6 +79,8 @@ const VideoPlayer = forwardRef<IVideoHandle, IVideoPlayerProps>(
7879 ref ,
7980 ) {
8081 const videoRef = useRef < HTMLVideoElement > ( null ) ;
82+ const wrapperRef = useRef < HTMLDivElement > ( null ) ;
83+ const [ isFullscreen , setIsFullscreen ] = useState ( false ) ;
8184 // controlsRef removed; controls are separate component
8285
8386 // 재생/일시정지 플래시 아이콘
@@ -100,6 +103,43 @@ const VideoPlayer = forwardRef<IVideoHandle, IVideoPlayerProps>(
100103 } , 650 ) ;
101104 } ;
102105
106+ const handleToggleFullscreen = useCallback ( ( ) => {
107+ if ( ! wrapperRef . current ) return ;
108+
109+ if ( ! document . fullscreenElement ) {
110+ wrapperRef . current . requestFullscreen ( ) . catch ( ( err ) => {
111+ console . error (
112+ `Error attempting to enable full-screen mode: ${ err . message } ` ,
113+ ) ;
114+ } ) ;
115+ } else {
116+ document . exitFullscreen ( ) ;
117+ }
118+ } , [ ] ) ;
119+
120+ useEffect ( ( ) => {
121+ const handleFullscreenChange = ( ) => {
122+ setIsFullscreen ( ! ! document . fullscreenElement ) ;
123+ } ;
124+
125+ document . addEventListener ( "fullscreenchange" , handleFullscreenChange ) ;
126+ document . addEventListener (
127+ "webkitfullscreenchange" ,
128+ handleFullscreenChange ,
129+ ) ;
130+
131+ return ( ) => {
132+ document . removeEventListener (
133+ "fullscreenchange" ,
134+ handleFullscreenChange ,
135+ ) ;
136+ document . removeEventListener (
137+ "webkitfullscreenchange" ,
138+ handleFullscreenChange ,
139+ ) ;
140+ } ;
141+ } , [ ] ) ;
142+
103143 const {
104144 playing,
105145 muted,
@@ -127,6 +167,7 @@ const VideoPlayer = forwardRef<IVideoHandle, IVideoPlayerProps>(
127167 toggle : ( ) => toggle ?.( ) ,
128168 mute : ( m ?: boolean ) => mute ?.( m ) ,
129169 seek : ( t : number ) => seek ?.( t ) ,
170+ toggleFullscreen : handleToggleFullscreen ,
130171 getEl : ( ) => videoRef . current ,
131172 } ) ) ;
132173
@@ -193,24 +234,42 @@ const VideoPlayer = forwardRef<IVideoHandle, IVideoPlayerProps>(
193234 const ratioNum = parseAspectRatioToNumber ( aspectRatio ) ;
194235 const aspectCss =
195236 typeof aspectRatio === "number" ? aspectRatio : ( aspectRatio ?? "16 / 9" ) ;
196- const maxWFromHeightExpr = `calc((100dvh - ${ viewportOffsetPx } px) * ${ ratioNum } )` ;
237+ const maxWFromHeightExpr = `calc((100dvh - ${ isFullscreen ? 0 : viewportOffsetPx } px) * ${ ratioNum } )` ;
197238 return (
198- < Stack spacing = { 1 } sx = { { width : "100%" , color : "common.white" } } >
239+ < Stack
240+ spacing = { isFullscreen ? 0 : 1 }
241+ sx = { {
242+ width : "100%" ,
243+ height : isFullscreen ? "100%" : "auto" ,
244+ color : "common.white" ,
245+ } }
246+ >
199247 { /* 비디오 영역: 남은 높이를 꽉 채우되 16:9 유지 */ }
200248 < Box
249+ ref = { wrapperRef }
201250 sx = { {
202- width : fitViewport ? `min(100%, ${ maxWFromHeightExpr } )` : "100%" ,
251+ width :
252+ fitViewport && ! isFullscreen
253+ ? `min(100%, ${ maxWFromHeightExpr } )`
254+ : "100%" ,
255+ height : isFullscreen ? "100dvh" : "auto" ,
203256 mx : "auto" ,
204257 alignSelf : "center" ,
258+ display : "flex" ,
259+ flexDirection : "column" ,
260+ justifyContent : "center" ,
261+ bgcolor : "black" ,
205262 } }
206263 >
207264 < Box
208265 sx = { {
209266 position : "relative" ,
210267 width : "100%" ,
268+ height : isFullscreen ? "auto" : "100%" ,
269+ maxHeight : isFullscreen ? "100dvh" : "unset" ,
211270 overflow : "hidden" ,
212271 bgcolor : "black" ,
213- aspectRatio : aspectCss ,
272+ aspectRatio : isFullscreen ? "unset" : aspectCss ,
214273 } }
215274 onPointerEnter = { ( ) => showControls ( ) }
216275 onPointerMove = { ( ) => showControls ( ) }
@@ -316,6 +375,8 @@ const VideoPlayer = forwardRef<IVideoHandle, IVideoPlayerProps>(
316375 v . currentTime = next ;
317376 setScrub ( null ) ;
318377 } }
378+ isFullscreen = { isFullscreen }
379+ onToggleFullscreen = { handleToggleFullscreen }
319380 visible = { controlsVisible }
320381 />
321382
0 commit comments