Skip to content

Commit

Permalink
메인페이지 캐러셀, 뷰포트 애니메이션 구현#263
Browse files Browse the repository at this point in the history
  • Loading branch information
HyerimKimm committed Sep 11, 2023
1 parent 6cf3f0d commit 79541ac
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 14 deletions.
9 changes: 9 additions & 0 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@egjs/flicking-plugins": "^4.7.1",
"@egjs/react-flicking": "^4.11.0",
"@react-oauth/google": "^0.11.1",
"@reduxjs/toolkit": "^1.9.5",
Expand Down
5 changes: 5 additions & 0 deletions client/src/assets/images/icons/arrow/carouselNext.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions client/src/assets/images/icons/arrow/carouselPrev.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion client/src/components/UploadPage/CourseUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { useToken } from "../../hooks/useToken";

const CourseUpload = () => {
const isDark = useSelector(state=>state.uiSetting.isDark);
const token = useSelector((state) => state.loginInfo.accessToken);
const imgRef = useRef();
const videoRef = useRef();
const navigate = useNavigate();
Expand Down
43 changes: 37 additions & 6 deletions client/src/components/mainPageItems/Carousel.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,49 @@
import React from 'react';
import Flicking, { MoveEvent, WillChangeEvent } from "@egjs/react-flicking";
import { styled } from 'styled-components';
import carousel1 from '../../assets/images/carousels/carousel1.png';
import carousel2 from '../../assets/images/carousels/carousel2.png';
import carousel3 from '../../assets/images/carousels/carousel3.png';
import { AutoPlay } from "@egjs/flicking-plugins";
import Flicking, { ViewportSlot, MoveEvent, WillChangeEvent, Viewport } from "@egjs/react-flicking";
import { Arrow } from "@egjs/flicking-plugins";
import "@egjs/flicking-plugins/dist/arrow.css";
import carouselPrev from '../../assets/images/icons/arrow/carouselPrev.svg';
import carouselNext from '../../assets/images/icons/arrow/carouselNext.svg';

const CarouselContainer = styled.div`
height: 600px;
max-height: 450px;
`
const CarouselItemContainer = styled.div`
`
const CarouselImg = styled.img`
width: 100%;
height: 100%;
object-fit: cover;
width: 95%;
height: 95%;
object-fit: contain;
`
const CarouselArrowButton = styled.span`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&.flicking-arrow-prev {
color: red;
}
`

const Carousel = () => {
const plugins = [ new AutoPlay({
duration: 1500,
animationDuration: 2000,
direction: "NEXT",
stopOnHover: true }),
new Arrow({}),
];

return (
<CarouselContainer>
<Flicking
duration={2000}
viewportTag='div'
cameraTag='div'
cameraClass=""
Expand All @@ -29,7 +53,10 @@ const Carousel = () => {
onMove={(e) => {}}
onWillChange={(e) => {}}
horizontal={true}
circular= {true}>
circular= {true}
moveType='snap'
threshold={50}
plugins={plugins}>
<CarouselItemContainer>
<CarouselImg src={carousel1}/>
</CarouselItemContainer>
Expand All @@ -39,6 +66,10 @@ const Carousel = () => {
<CarouselItemContainer>
<CarouselImg src={carousel3}/>
</CarouselItemContainer>
<ViewportSlot>
<CarouselArrowButton className="flicking-arrow-prev is-thin"></CarouselArrowButton>
<CarouselArrowButton className="flicking-arrow-next is-thin"></CarouselArrowButton>
</ViewportSlot>
</Flicking>
</CarouselContainer>
);
Expand Down
69 changes: 63 additions & 6 deletions client/src/components/mainPageItems/MainSecondPageItems.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ const frameInLeftToRightAnimation = keyframes`
}
`;

const frameInRightToLeftAnimation = keyframes`
0% {
opacity: 0;
transform: translateX(20%);
}
100% {
opacity: 1;
transform: translateX(0%);
}
`

const MainPageSecontItemContainer = styled.section`
padding: ${globalTokens.Spacing32.value}px;
border-radius: ${globalTokens.BigRadius.value}px;
Expand All @@ -26,19 +37,65 @@ const MainPageSecontItemContainer = styled.section`
justify-content: center;
align-items: center;
`

const SecondPageTitleTypo = styled(MainPageTitleTypo)`
&.second-frame-in {
animation: ${frameInLeftToRightAnimation} 1.5s;
}
&.second-frame-out {
opacity: 0;
}
`
const SecondPageSubTitleTypo = styled(MainPageSubTitleTypo)`
&.second-frame-in {
animation: ${frameInRightToLeftAnimation} 1.5s;
}
&.second-frame-out {
opacity: 0;
}
`

export const MainSecondPageItems = () => {
const isDark = useSelector(state=>state.uiSetting.isDark);

const ref = useRef();
const [ isInTitleViewport, setIsInTitleViewport ] = useState(false);
const [ isInSubTitleViewport, setIsInSubTitleViewport ] = useState(false);

useEffect(()=>{
if(!ref.current) return;
const callback = (entries) => {
entries.forEach((entry)=>{
if(entry.isIntersecting){
setIsInTitleViewport(true);
setTimeout(()=>{
setIsInSubTitleViewport(true)
},100);
} else {
setIsInTitleViewport(false);
setIsInSubTitleViewport(false);
}
})
}
const options = { root: null, rootMargin: "0px", threshold: 0 };
const observer = new IntersectionObserver(callback, options);
observer.observe(ref.current); // 요소 관찰 시작

return () => {
observer.disconnect(); // 컴포넌트 언마운트 시 관찰 중단
}
},[])
return (
<MainPageSecontItemContainer>
<MainPageTitleTypo isDark={isDark}>
<SecondPageTitleTypo
isDark={isDark}
className={isInTitleViewport?'second-frame-in':'second-frame-out'}
ref={ref}>
Growth & Rewards
</MainPageTitleTypo>
<MainPageSubTitleTypo isDark={isDark}>
</SecondPageTitleTypo>
<SecondPageSubTitleTypo
isDark={isDark}
className={isInSubTitleViewport?'second-frame-in':'second-frame-out'}>
성장은 기본, 영상으로 수익 창출까지!
</MainPageSubTitleTypo>
</SecondPageSubTitleTypo>
<Carousel/>
</MainPageSecontItemContainer>
);
Expand Down
4 changes: 4 additions & 0 deletions client/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,8 @@ code {
}
::-webkit-scrollbar {
width: 0px
}
.flicking-arrow-prev,
.flicking-arrow-next {
color: red;
}
1 change: 0 additions & 1 deletion client/src/pages/contents/CourseUploadPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useSelector } from "react-redux";
import { PageContainer } from "../../atoms/layouts/PageContainer";
import CourseUpload from "../../components/UploadPage/CourseUpload";
import tokens from '../../styles/tokens.json';
import { useSelector } from "react-redux";
import { Heading5Typo } from "../../atoms/typographys/Typographys";

const globalTokens = tokens.global;
Expand Down

0 comments on commit 79541ac

Please sign in to comment.