-
Notifications
You must be signed in to change notification settings - Fork 1
Fix/new rending #176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/new rending #176
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,39 +16,41 @@ const KAKAO_AUTH_URL = `https://dev.say-cheese.me/oauth2/authorization/kakao`; | |
| export const RendingBody = () => { | ||
| const [api, setApi] = useState<CarouselApi>(); | ||
| const [current, setCurrent] = useState(0); | ||
| const [touchStart, setTouchStart] = useState(0); | ||
| const [touchEnd, setTouchEnd] = useState(0); | ||
| const searchParams = useSearchParams(); | ||
| const redirect = searchParams.get('redirect'); | ||
|
|
||
| const slides = [ | ||
| { | ||
| src: '/assets/rending/new-swipe/1.png', | ||
| src: '/assets/rending/new-swipe/1.svg', | ||
| alt: '앨범 목록 화면', | ||
| width: 260, | ||
| height: 530, | ||
| height: 530.31, | ||
| title: '이벤트마다 만드는 공유앨범', | ||
| description: '감튀 모임부터 찐친 여행까지', | ||
| }, | ||
| { | ||
| src: '/assets/rending/new-swipe/2.png', | ||
| src: '/assets/rending/new-swipe/2.svg', | ||
| alt: 'QR 코드 공유', | ||
| width: 260, | ||
| height: 530, | ||
| height: 530.31, | ||
| title: '이벤트마다 모인 자리에서 바로 공유', | ||
| description: '감튀 모임부터 앨범 만들고 초대까지 딱 10초', | ||
| }, | ||
| { | ||
| src: '/assets/rending/new-swipe/3.png', | ||
| src: '/assets/rending/new-swipe/3.svg', | ||
| alt: '베스트컷', | ||
| width: 312.5, | ||
| height: 530.3, | ||
| width: 312.56, | ||
| height: 530.31, | ||
| title: '이벤트마다 한눈에 보는 베스트컷', | ||
| description: '사진 고르는 고민 이제 끝', | ||
| }, | ||
| { | ||
| src: '/assets/rending/new-swipe/4.png', | ||
| src: '/assets/rending/new-swipe/4.svg', | ||
| alt: '네컷추억', | ||
| width: 289, | ||
| height: 530, | ||
| width: 288.8, | ||
| height: 530.31, | ||
| title: '딱 네컷으로 남는 추억', | ||
| description: '앨범이 닫히면 사라지는 원본 사진들', | ||
| }, | ||
|
|
@@ -63,6 +65,29 @@ export const RendingBody = () => { | |
| }); | ||
| }, [api]); | ||
|
|
||
| const handleTouchStart = (e: React.TouchEvent) => { | ||
| setTouchStart(e.targetTouches[0].clientX); | ||
| }; | ||
|
|
||
| const handleTouchMove = (e: React.TouchEvent) => { | ||
| setTouchEnd(e.targetTouches[0].clientX); | ||
| }; | ||
|
|
||
| const handleTouchEnd = () => { | ||
| if (!api) return; | ||
|
|
||
| const swipeDistance = touchStart - touchEnd; | ||
| const minSwipeDistance = 50; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| if (swipeDistance > minSwipeDistance) { | ||
| // 왼쪽으로 스와이프 (다음) | ||
| api.scrollNext(); | ||
| } else if (swipeDistance < -minSwipeDistance) { | ||
| // 오른쪽으로 스와이프 (이전) | ||
| api.scrollPrev(); | ||
| } | ||
| }; | ||
|
|
||
| const handleKakaoLogin = async () => { | ||
| try { | ||
| const kakaoUrl = redirect | ||
|
|
@@ -77,62 +102,86 @@ export const RendingBody = () => { | |
|
|
||
| return ( | ||
| <section className='bg-background-white-muted relative flex h-screen w-full flex-col'> | ||
| {/* 캐러셀 영역 */} | ||
| {/* 이미지 영역 - 고정 (애니메이션 없음) */} | ||
| <div className='flex h-screen w-full flex-col items-center justify-start px-4 pt-12'> | ||
| <div | ||
| className='relative w-full max-w-md' | ||
| onTouchStart={handleTouchStart} | ||
| onTouchMove={handleTouchMove} | ||
| onTouchEnd={handleTouchEnd} | ||
| > | ||
| {slides.map((slide, index) => ( | ||
| <div | ||
| key={index} | ||
| className={`flex items-center justify-center overflow-hidden rounded-3xl transition-opacity duration-500 ${ | ||
| current === index | ||
| ? 'relative opacity-100' | ||
| : 'pointer-events-none absolute inset-0 opacity-0' | ||
| }`} | ||
| > | ||
| <Image | ||
| src={slide.src} | ||
| alt={slide.alt} | ||
| width={slide.width} | ||
| height={slide.height} | ||
| className='object-contain' | ||
| priority={index === 0} | ||
| /> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| </div> | ||
|
|
||
| {/* 하단 흰색 배경 영역 */} | ||
| <div | ||
| className='absolute bottom-0 z-10 flex w-full flex-col items-center bg-white px-4 pt-8' | ||
| style={{ paddingBottom: 'calc(env(safe-area-inset-bottom) + 20px)' }} | ||
| > | ||
| {/* 텍스트 및 인디케이터 영역 - 스와이프 가능 */} | ||
| <Carousel | ||
| setApi={setApi} | ||
| className='w-full max-w-md' | ||
| className='w-full' | ||
| opts={{ | ||
| loop: true, | ||
| loop: false, | ||
| align: 'center', | ||
| }} | ||
| > | ||
| <CarouselContent> | ||
| {slides.map((slide, index) => ( | ||
| <CarouselItem key={index}> | ||
| <div className='flex items-center justify-center overflow-hidden rounded-3xl'> | ||
| <Image | ||
| src={slide.src} | ||
| alt={slide.alt} | ||
| width={slide.width} | ||
| height={slide.height} | ||
| className='object-contain' | ||
| priority={index === 0} | ||
| /> | ||
| <div className='flex flex-col items-center'> | ||
| {/* 텍스트 영역 */} | ||
| <div className='mb-6 flex flex-col items-center text-center'> | ||
| <h2 className='text-text-basic text-[24px] font-[600]'> | ||
| {slide.title} | ||
| </h2> | ||
| <p className='mt-1 text-[16px] font-[500] text-[#746181]'> | ||
| {slide.description} | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* 인디케이터 점들 */} | ||
| <div className='flex gap-2'> | ||
| {slides.map((_, idx) => ( | ||
| <button | ||
| key={idx} | ||
| onClick={() => api?.scrollTo(idx)} | ||
| className={`h-1.5 rounded-full transition-all ${ | ||
| current === idx | ||
| ? 'w-6 bg-gray-700' | ||
| : 'w-1.5 bg-gray-200' | ||
| }`} | ||
| aria-label={`슬라이드 ${idx + 1}로 이동`} | ||
| /> | ||
| ))} | ||
| </div> | ||
| </div> | ||
| </CarouselItem> | ||
| ))} | ||
| </CarouselContent> | ||
| </Carousel> | ||
|
Comment on lines
141
to
182
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 현재 캐러셀의 각 아이템( |
||
| </div> | ||
|
|
||
| {/* 하단 흰색 배경 영역 - 이미지 위에 오버레이 */} | ||
| <div className='absolute bottom-0 z-10 flex h-[242px] w-full flex-col items-center bg-white px-4 pt-8 pb-5'> | ||
| {/* 텍스트 영역 */} | ||
| <div className='mb-6 flex flex-col items-center text-center'> | ||
| <h2 className='text-text-basic text-[24px] font-[600]'> | ||
| {slides[current].title} | ||
| </h2> | ||
| <p className='mt-1 text-[16px] font-[500] text-[#746181]'> | ||
| {slides[current].description} | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* 인디케이터 점들 */} | ||
| <div className='flex gap-2'> | ||
| {slides.map((_, index) => ( | ||
| <button | ||
| key={index} | ||
| onClick={() => api?.scrollTo(index)} | ||
| className={`h-1.5 rounded-full transition-all ${ | ||
| current === index ? 'w-6 bg-gray-700' : 'w-1.5 bg-gray-200' | ||
| }`} | ||
| aria-label={`슬라이드 ${index + 1}로 이동`} | ||
| /> | ||
| ))} | ||
| </div> | ||
|
|
||
| {/* 카카오 로그인 버튼 */} | ||
| {/* 카카오 로그인 버튼 - 고정 */} | ||
| <div | ||
| className='mt-auto flex h-[56px] w-full cursor-pointer items-center justify-center gap-2 rounded-[6px] bg-[#FEE500]' | ||
| onClick={handleKakaoLogin} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
touchStart와touchEnd값을useState로 관리하면handleTouchMove가 호출될 때마다 불필요한 리렌더링이 발생하여 성능이 저하될 수 있습니다. 터치 이동 중 좌표는 렌더링에 직접적인 영향을 주지 않으므로,useRef를 사용하여 값을 관리하는 것이 더 효율적입니다.useRef로 변경하고 관련 핸들러 함수들도 수정해주세요.