diff --git a/src/components/projectDetail/Carousel.tsx b/src/components/projectDetail/Carousel.tsx index 254b55d..8b428d5 100644 --- a/src/components/projectDetail/Carousel.tsx +++ b/src/components/projectDetail/Carousel.tsx @@ -1,24 +1,74 @@ import useEmblaCarousel from 'embla-carousel-react'; import { EmblaOptionsType } from 'embla-carousel'; import YouTube from 'react-youtube'; -import { useCallback, useContext, useEffect, useState } from 'react'; +import { useCallback, useContext, useEffect, useRef, useState } from 'react'; import { ProjectDetailContext } from '@/context/ProjectDetailContext'; import * as s from '@/style/projectDetail/CarouselStyle'; import { ZoomContext } from '@/context/ZoomContext'; import ButtonBox from '@/components/projectDetail/ButtonBox'; export default function Carousel() { + interface ThumbnailType { + url: string; + type: string; + order: number; + } + const options: EmblaOptionsType = { align: 'center', loop: true, slidesToScroll: 2 }; const [emblaRef, emblaApi] = useEmblaCarousel(options); const { projectInfo } = useContext(ProjectDetailContext); const { setStartImg, setShowZoomComponent } = useContext(ZoomContext); const [currentImg, setCurrentImg] = useState(0); - const img = new Image(); + const [thumbnails, setThumbnails] = useState([]); + const [imgDirection, setImgDirection] = useState([]); + const canvasRef = useRef(null); const projectLength = projectInfo.projectMedia.length; - const slides = - projectInfo.projectMedia.length <= 3 - ? [...projectInfo.projectMedia, ...projectInfo.projectMedia] - : projectInfo.projectMedia; + + useEffect(() => { + const slides = + projectInfo.projectMedia.length <= 3 + ? [...projectInfo.projectMedia, ...projectInfo.projectMedia] + : projectInfo.projectMedia; + const thumbnailArray: ThumbnailType[] = []; + + slides.forEach((imgObj, idx) => { + const tmpImg = new Image(); + tmpImg.src = imgObj.url; + tmpImg.crossOrigin = 'anonymous'; + + tmpImg.onload = () => { + const canvas = canvasRef.current; + if (!canvas) return; + + canvas.width = tmpImg.width; + canvas.height = tmpImg.height; + + const ctx = canvas.getContext('2d'); + if (!ctx) return; + + ctx.drawImage(tmpImg, 0, 0); + const thumbnail = canvas.toDataURL('image/png'); + + if (imgObj.mediaType === 'IMAGE') { + thumbnailArray[idx] = { + url: thumbnail, + type: imgObj.mediaType, + order: imgObj.order, + }; + } else { + thumbnailArray[idx] = { + url: imgObj.url, + type: imgObj.mediaType, + order: imgObj.order, + }; + } + + if (thumbnailArray.length === slides.length) { + setThumbnails(thumbnailArray); + } + }; + }); + }, [projectInfo]); const onSelect = useCallback(() => { if (!emblaApi) return; @@ -31,18 +81,39 @@ export default function Carousel() { emblaApi.on('select', onSelect); }, [emblaApi, onSelect]); + useEffect(() => { + const loadImgDirection = async () => { + const directions = await Promise.all( + thumbnails.map((carouselObj) => { + return new Promise((resolve) => { + const img = new Image(); + img.src = carouselObj.url; + + img.onload = () => { + if (img.width > img.height) { + resolve('row'); + } else { + resolve('col'); + } + }; + }); + }), + ); + + setImgDirection(directions); + }; + + loadImgDirection(); + }, [thumbnails]); + return ( + - {slides.map((carouselObj, index) => { - img.src = carouselObj.url; - let type = 'row'; - if (img.width < img.height) { - type = 'col'; - } - if (carouselObj.mediaType === 'VIDEO') { + {thumbnails.map((carouselObj, index) => { + if (carouselObj.type === 'VIDEO') { return ( { if (index > projectInfo.projectMedia.length - 1) { setStartImg(index - projectInfo.projectMedia.length); @@ -76,7 +147,7 @@ export default function Carousel() { })} - {slides.map((_carouselObj, index) => { + {thumbnails.map((_carouselObj, index) => { if (index < projectLength / 2) { return ( { - if (img.width > img.height || carouselImgs[startImg].mediaType === 'VIDEO') { - setImgDirection('row'); - } else { - setImgDirection('col'); - } - }, [startImg, img.width, carouselImgs, img.height]); + const img = new Image(); + img.src = carouselImgs[startImg].url; + + img.onload = () => { + if (img.width > img.height) { + setImgDirection('row'); + } else { + setImgDirection('col'); + } + }; + }, [carouselImgs, startImg]); useEffect(() => { const MouseMoveFunction = (e: MouseEvent) => { diff --git a/src/style/ZoomStyle/ZoomMediaStyle.tsx b/src/style/ZoomStyle/ZoomMediaStyle.tsx index c694a56..dc5d9de 100644 --- a/src/style/ZoomStyle/ZoomMediaStyle.tsx +++ b/src/style/ZoomStyle/ZoomMediaStyle.tsx @@ -23,11 +23,10 @@ export const Div = styled.div<{ $zoomCount: number; $type: string }>` return 70 * $zoomCount; } if ($type === 'col') { - return 27 * $zoomCount; + return 23 * $zoomCount; } - return 100; }}%; - height: ${({ $type }) => ($type === 'row' ? '80%' : '85%')}; + height: ${({ $type }) => ($type === 'row' ? '80%' : '90%')}; position: relative; display: flex; align-items: center; diff --git a/src/style/projectDetail/FloatingBoxStyle.tsx b/src/style/projectDetail/FloatingBoxStyle.tsx index dc626d0..7b8f770 100644 --- a/src/style/projectDetail/FloatingBoxStyle.tsx +++ b/src/style/projectDetail/FloatingBoxStyle.tsx @@ -5,7 +5,7 @@ export const Section = styled.section<{ $buttonNum: number }>` margin-bottom: 470px; padding: 16px 16px 8px 16px; width: 220px; - height: calc(375px + ${({ $buttonNum }) => $buttonNum * 36}px); + height: calc(397px + ${({ $buttonNum }) => $buttonNum * 36}px); box-sizing: border-box; border-radius: 4px; box-shadow: @@ -63,6 +63,7 @@ export const View = styled.p` `; export const PromotionBox = styled.div` + padding-bottom: 8px; width: 188px; border-bottom: 1px solid #cfebff7f; display: flex; @@ -134,10 +135,10 @@ export const CoffeeChatText = styled.p` export const Title = styled.p` color: #171719; - font-size: 11px; - font-weight: 590; - line-height: 13px; - letter-spacing: 0.06px; + font-size: 14px; + font-weight: 600; + line-height: 142.9%; + letter-spacing: 0.203px; `; export const ImgBox = styled.div` diff --git a/src/style/projectDetail/PerformanceStyle.tsx b/src/style/projectDetail/PerformanceStyle.tsx index 79ae643..fd18bfd 100644 --- a/src/style/projectDetail/PerformanceStyle.tsx +++ b/src/style/projectDetail/PerformanceStyle.tsx @@ -21,7 +21,6 @@ export const AwardBox = styled.section` export const Award = styled.section` margin-bottom: 8px; width: 256px; - height: 140px; display: flex; flex-direction: column; justify-content: space-evenly;