1- import { useCallback , useEffect } from 'react'
1+ import React , { useCallback , useEffect , useState , useMemo } from 'react'
22import Image from 'next/image'
33import Link from 'next/link'
44import CameraCaptureButton from '@/assets/CameraCaptureButton.svg'
@@ -26,6 +26,7 @@ function CameraView({
2626} : CameraViewProps ) {
2727 const { activeTooltip, hideTooltip, showTooltip } = useTooltipStore ( )
2828 const { currentMission, setCurrentMission } = useMissionStore ( )
29+ const [ videoSize , setVideoSize ] = useState ( { width : 0 , height : 0 } )
2930
3031 const adjustVideoSize = useCallback ( ( ) => {
3132 if ( videoRef . current ) {
@@ -35,33 +36,37 @@ function CameraView({
3536 const containerAspect = container . clientWidth / container . clientHeight
3637 const videoAspect = video . videoWidth / video . videoHeight
3738
39+ let newWidth
40+ let newHeight
41+
3842 if ( containerAspect > videoAspect ) {
39- video . style . width = '100%'
40- video . style . height = 'auto'
43+ newHeight = container . clientHeight
44+ newWidth = newHeight * videoAspect
4145 } else {
42- video . style . width = 'auto'
43- video . style . height = '100%'
46+ newWidth = container . clientWidth
47+ newHeight = newWidth / videoAspect
4448 }
49+
50+ setVideoSize ( { width : newWidth , height : newHeight } )
4551 }
4652 }
47- } , [ ] )
53+ } , [ videoRef ] )
4854
4955 useEffect ( ( ) => {
50- window . addEventListener ( 'resize' , adjustVideoSize )
51- return ( ) => {
52- window . removeEventListener ( 'resize' , adjustVideoSize )
56+ const video = videoRef . current
57+ if ( video ) {
58+ const handleLoadedMetadata = ( ) => adjustVideoSize ( )
59+ video . addEventListener ( 'loadedmetadata' , handleLoadedMetadata )
60+ return ( ) =>
61+ video . removeEventListener ( 'loadedmetadata' , handleLoadedMetadata )
5362 }
54- } , [ adjustVideoSize ] )
63+ return undefined
64+ } , [ videoRef , adjustVideoSize ] )
5565
5666 useEffect ( ( ) => {
57- if ( videoRef . current ) {
58- videoRef . current . addEventListener ( 'loadedmetadata' , adjustVideoSize )
59- }
60- return ( ) => {
61- if ( videoRef . current ) {
62- videoRef . current . removeEventListener ( 'loadedmetadata' , adjustVideoSize )
63- }
64- }
67+ const handleResize = ( ) => adjustVideoSize ( )
68+ window . addEventListener ( 'resize' , handleResize )
69+ return ( ) => window . removeEventListener ( 'resize' , handleResize )
6570 } , [ adjustVideoSize ] )
6671
6772 useEffect ( ( ) => {
@@ -70,40 +75,59 @@ function CameraView({
7075 } else {
7176 showTooltip ( 'mission' )
7277 }
78+ return undefined
7379 } , [ currentMission , hideTooltip , showTooltip ] )
7480
81+ const missionButton = useMemo (
82+ ( ) => (
83+ < Link href = "/create-mission" >
84+ < div className = "flex justify-between items-center px-3 py-2 rounded-[14px] bg-gray-200 text-body2 text-gray-700" >
85+ { currentMission ? (
86+ < > 미션 바꾸기</ >
87+ ) : (
88+ < >
89+ < Image src = { PlusGray } alt = "Plus Gray" className = "w-4 h-4 mr-2" />
90+ 미션 추가하기
91+ </ >
92+ ) }
93+ </ div >
94+ { ! currentMission && activeTooltip === 'mission' && (
95+ < Tooltip
96+ message = "내 사진에 미션을 더 해봐요!"
97+ onClose = { hideTooltip }
98+ position = "bottom"
99+ arrowClassName = "left-12"
100+ className = "top-12 left-28"
101+ />
102+ ) }
103+ </ Link >
104+ ) ,
105+ [ currentMission , activeTooltip , hideTooltip ] ,
106+ )
107+
108+ const missionDisplay = useMemo (
109+ ( ) =>
110+ currentMission ? (
111+ < div className = "flex justify-center text-gray-50 bg-point-mint px-3 py-2 rounded-[14px] text-sm" >
112+ { currentMission }
113+ < button onClick = { ( ) => setCurrentMission ( null ) } className = "ml-2" >
114+ X
115+ </ button >
116+ </ div >
117+ ) : (
118+ < div className = "flex justify-center text-gray-500 bg-gray-200 px-3 py-2 rounded-[14px] text-sm" >
119+ 모임의 순간을 담아주세요!
120+ </ div >
121+ ) ,
122+ [ currentMission , setCurrentMission ] ,
123+ )
124+
75125 return (
76- < div className = "flex flex-col min-h-screen w-full " >
126+ < div className = "flex flex-col min-h-screen w-full" >
77127 { /* header */ }
78128 < div className = "p-4" >
79129 < div className = "flex justify-between items-center h-12 w-full" >
80- < div className = "relative" >
81- < Link href = "/create-mission" >
82- < div className = "flex justify-between items-center px-3 py-2 rounded-[14px] bg-gray-200 text-body2 text-gray-700" >
83- { currentMission ? (
84- < > 미션 바꾸기</ >
85- ) : (
86- < >
87- < Image
88- src = { PlusGray }
89- alt = "Plus Gray"
90- className = "w-4 h-4 mr-2"
91- />
92- 미션 추가하기
93- </ >
94- ) }
95- </ div >
96- { ! currentMission && activeTooltip === 'mission' && (
97- < Tooltip
98- message = "내 사진에 미션을 더 해봐요!"
99- onClose = { hideTooltip }
100- position = "bottom"
101- arrowClassName = "left-12"
102- className = "top-12 left-28"
103- />
104- ) }
105- </ Link >
106- </ div >
130+ < div className = "relative" > { missionButton } </ div >
107131 < div className = "flex-1" />
108132 < button
109133 tabIndex = { 0 }
@@ -126,30 +150,19 @@ function CameraView({
126150 ref = { videoRef }
127151 autoPlay
128152 playsInline
129- className = "absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 min-w-full min-h-full w-auto h-auto max-w-none"
153+ className = "absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 min-w-full min-h-full w-auto h-auto max-w-none object-cover "
130154 style = { {
131- transform : `${ isRearCamera ? '' : 'scaleX(-1)' } translate(-50%, -50%)` ,
155+ width : `${ videoSize . width } px` ,
156+ height : `${ videoSize . height } px` ,
157+ transform : `translate(-50%, -50%) ${ isRearCamera ? '' : 'scaleX(-1)' } ` ,
132158 } }
133159 />
134160 </ div >
135161 </ div >
136162
137163 { /* footer */ }
138164 < div className = "flex flex-col mt-auto mb-9" >
139- < div className = "flex justify-center" >
140- { currentMission ? (
141- < div className = "flex justify-center text-gray-50 bg-point-mint px-3 py-2 rounded-[14px] text-sm" >
142- { currentMission }
143- < button onClick = { ( ) => setCurrentMission ( null ) } className = "ml-2" >
144- X
145- </ button >
146- </ div >
147- ) : (
148- < div className = "flex justify-center text-gray-500 bg-gray-200 px-3 py-2 rounded-[14px] text-sm" >
149- 모임의 순간을 담아주세요!
150- </ div >
151- ) }
152- </ div >
165+ < div className = "flex justify-center" > { missionDisplay } </ div >
153166
154167 < div className = "flex items-center justify-center w-full mt-5" >
155168 < button
0 commit comments