Skip to content
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

[SP3/refactor] 랜딩 페이지 intersection observer 적용 #326

Open
wants to merge 2 commits into
base: SP3/refactor
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 50 additions & 43 deletions src/Onboarding/components/frame/Frame1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import { TEXT_ROLLING } from '../../constants/TEXT_ROLLING';
import { ImgPopUp, popUp } from '../../styles/animation';
import { sectionStyle } from '../../styles/common';

const Frame1 = () => {
interface Frame1Props {
isInView: boolean;
refCallback: (elem: HTMLSelectElement) => void;
}

const Frame1 = ({ isInView, refCallback }: Frame1Props) => {
const [textIdx, setTextIdx] = useState(0);

useEffect(() => {
Expand All @@ -28,7 +33,7 @@ const Frame1 = () => {
});

return (
<section css={section}>
<section id="frame1" ref={refCallback} css={section}>
<div css={imgSlide} />
<StRollingTextBox>
{TEXT_ROLLING.filter((_, idx) => idx === textIdx).map((text) => (
Expand All @@ -41,50 +46,52 @@ const Frame1 = () => {
<StCtaLink to="/sign-in" target="_blank" className="click_service">
오픈 베타 시작하기
</StCtaLink>
<div css={imgContainer}>
<div css={fixedBackground} />
<picture>
<source srcSet={webpFrame1ObjectiveItem} type="image/webp" />
<StLeftLateImgPopUp
fromX={17.7}
fromY={0}
toX={17.7}
toY={-15.8}
delay={1}
src={imgFrame1ObjectiveItem}
alt="objective-img"
width={262}
height={235}
/>
</picture>
<StDashboardContainer>
{isInView && (
<div css={imgContainer}>
<div css={fixedBackground} />
<picture>
<source srcSet={webpFrame1MainDashboard} type="image/webp" />
<StImgDashboardPopUp
fromY={20}
toY={0}
src={imgFrame1MainDashboard}
alt="dashboard-img"
width={996}
height={560}
<source srcSet={webpFrame1ObjectiveItem} type="image/webp" />
<StLeftLateImgPopUp
fromX={17.7}
fromY={0}
toX={17.7}
toY={-15.8}
delay={1}
src={imgFrame1ObjectiveItem}
alt="objective-img"
width={262}
height={235}
/>
</picture>
<StDashboardContainer>
<picture>
<source srcSet={webpFrame1MainDashboard} type="image/webp" />
<StImgDashboardPopUp
fromY={20}
toY={0}
src={imgFrame1MainDashboard}
alt="dashboard-img"
width={996}
height={560}
/>
</picture>
</StDashboardContainer>
<picture css={zIndex}>
<source srcSet={webpFrame1SideSheetRight} type="image/webp" />
<StRightLateImgPopUp
fromX={-18.7}
fromY={39}
toX={-18.7}
toY={19}
delay={1.5}
src={imgFrame1SideSheetRight}
alt="sidesheet-img"
width={272}
height={598}
/>
</picture>
</StDashboardContainer>
<picture css={zIndex}>
<source srcSet={webpFrame1SideSheetRight} type="image/webp" />
<StRightLateImgPopUp
fromX={-18.7}
fromY={39}
toX={-18.7}
toY={19}
delay={1.5}
src={imgFrame1SideSheetRight}
alt="sidesheet-img"
width={272}
height={598}
/>
</picture>
</div>
</div>
)}
</section>
);
};
Expand Down
12 changes: 7 additions & 5 deletions src/Onboarding/components/frame/Frame2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,25 @@ import { css } from '@emotion/react';
import imgFrame2TreeGraph from '../../assets/frame/imgFrame2TreeGraph.png';
import webpFrame2TreeGraph from '../../assets/frame/webpFrame2TreeGraph.webp';
import { CONTENTS } from '../../constants/CONTENTS';
import useScrollDetect from '../../hooks/useScrollDetect';
import { ImgPopUp } from '../../styles/animation';
import { sectionStyle } from '../../styles/common';
import TextField from './TextField';

const Frame2 = () => {
const { active, element } = useScrollDetect();
interface Frame2Props {
isInView: boolean;
refCallback: (elem: HTMLSelectElement) => void;
}

const Frame2 = ({ isInView, refCallback }: Frame2Props) => {
return (
<section css={section} ref={element}>
<section id="frame2" css={section} ref={refCallback}>
<TextField
subTitle={CONTENTS[1].subTitle!}
subTitleColor={CONTENTS[1].subTitleColor!}
title={CONTENTS[1].title}
description={CONTENTS[1].description!}
/>
{active && (
{isInView && (
<picture>
<source srcSet={webpFrame2TreeGraph} type="image/webp" />
<ImgPopUp
Expand Down
12 changes: 7 additions & 5 deletions src/Onboarding/components/frame/Frame3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,26 @@ import webpFrame3Question1 from '../../assets/frame/webpFrame3Question1.webp';
import webpFrame3Question2 from '../../assets/frame/webpFrame3Question2.webp';
import webpFrame3Question3 from '../../assets/frame/webpFrame3Question3.webp';
import { CONTENTS } from '../../constants/CONTENTS';
import useScrollDetect from '../../hooks/useScrollDetect';
import { ImgPopUp } from '../../styles/animation';
import { sectionStyle } from '../../styles/common';
import isWebPSupported from '../../utils/isWebPSupported';
import TextField from './TextField';

const Frame3 = () => {
const { active, element } = useScrollDetect();
interface Frame3Props {
isInView: boolean;
refCallback: (elem: HTMLSelectElement) => void;
}

const Frame3 = ({ isInView, refCallback }: Frame3Props) => {
return (
<section css={section} ref={element}>
<section id="frame3" css={section} ref={refCallback}>
<TextField
subTitle={CONTENTS[2].subTitle!}
subTitleColor={CONTENTS[2].subTitleColor!}
title={CONTENTS[2].title}
description={CONTENTS[2].description!}
/>
{active && (
{isInView && (
<div css={imgContainer}>
<picture>
<source srcSet={webpFrame3Question1} type="image/webp" />
Expand Down
12 changes: 7 additions & 5 deletions src/Onboarding/components/frame/Frame4.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,25 @@ import webpFrame4DashboardDark from '../../assets/frame/webpFrame4DashboardDark.
import webpFrame4SideSheetLeft from '../../assets/frame/webpFrame4SideSheetLeft.webp';
import webpFrame4SideSheetRight from '../../assets/frame/webpFrame4SideSheetRight.webp';
import { CONTENTS } from '../../constants/CONTENTS';
import useScrollDetect from '../../hooks/useScrollDetect';
import { ImgPopUp } from '../../styles/animation';
import { sectionStyle } from '../../styles/common';
import TextField from './TextField';

const Frame4 = () => {
const { active, element } = useScrollDetect();
interface Frame4Props {
isInView: boolean;
refCallback: (elem: HTMLSelectElement) => void;
}

const Frame4 = ({ isInView, refCallback }: Frame4Props) => {
return (
<section css={section} ref={element}>
<section id="frame4" css={section} ref={refCallback}>
<TextField
subTitle={CONTENTS[3].subTitle!}
subTitleColor={CONTENTS[3].subTitleColor!}
title={CONTENTS[3].title}
description={CONTENTS[3].description!}
/>
{active && (
{isInView && (
<div css={imgContainer}>
<picture css={zIndex}>
<source srcSet={webpFrame4SideSheetLeft} type="image/webp" />
Expand Down
13 changes: 8 additions & 5 deletions src/Onboarding/components/frame/Frame5.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ import imgFrame5List2 from '../../assets/frame/imgFrame5List2.png';
import imgFrame5List3 from '../../assets/frame/imgFrame5List3.png';
import imgFrame5List4 from '../../assets/frame/imgFrame5List4.png';
import { CONTENTS } from '../../constants/CONTENTS';
import useScrollDetect from '../../hooks/useScrollDetect';
import { ImgPopUp } from '../../styles/animation';
import { sectionStyle } from '../../styles/common';
import TextField from './TextField';

const Frame5 = () => {
interface Frame5Props {
isInView: boolean;
refCallback: (elem: HTMLSelectElement) => void;
}

const Frame5 = ({ isInView, refCallback }: Frame5Props) => {
const [isOpen, setIsOpen] = useState(false);
const { active, element } = useScrollDetect();

useEffect(() => {
const timer = setTimeout(() => {
Expand All @@ -27,14 +30,14 @@ const Frame5 = () => {
}, []);

return (
<section css={section} ref={element}>
<section id="frame5" css={section} ref={refCallback}>
<TextField
subTitle={CONTENTS[4].subTitle!}
subTitleColor={CONTENTS[4].subTitleColor!}
title={CONTENTS[4].title}
description={CONTENTS[4].description!}
/>
{active && (
{isInView && (
<StImgContainer>
{isOpen && (
<img src={imgFrame5HistoryOpen} alt="main-dashboard-img-1" width={1005} height={57} />
Expand Down
31 changes: 0 additions & 31 deletions src/Onboarding/hooks/useScrollDetect.tsx

This file was deleted.

58 changes: 53 additions & 5 deletions src/Onboarding/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { css } from '@emotion/react';
import { useCallback, useEffect, useRef, useState } from 'react';

import Frame1 from './components/frame/Frame1';
import Frame2 from './components/frame/Frame2';
Expand All @@ -9,13 +10,60 @@ import Frame6 from './components/frame/Frame6';
import OnboardingFooter from './components/layout/OnboardingFooter';

const Onboarding = () => {
const sectionsRef = useRef<HTMLSelectElement[]>([]);

const [sectionsUpdated, setSectionsUpdated] = useState(false);
const [isInView, setIsInView] = useState([true, false, false, false, false]);

const refCallback = useCallback((element: HTMLSelectElement) => {
if (element) {
sectionsRef.current.push(element);

if (sectionsRef.current.length === 5) {
setSectionsUpdated(true);
}
}
}, []);

useEffect(() => {
if (!sectionsUpdated) return;

const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const sectionId = entry.target.getAttribute('id');
const sectionIndex = ['frame1', 'frame2', 'frame3', 'frame4', 'frame5'].indexOf(
sectionId!,
);

if (entry.isIntersecting && !isInView[sectionIndex]) {
setIsInView((prev) => {
const updatedState = [...prev];
updatedState[sectionIndex] = entry.isIntersecting;
return updatedState;
});
}
});
},
{ root: null, rootMargin: '-500px' },
);

sectionsRef.current.forEach((section) => {
observer.observe(section);
});

return () => {
sectionsRef.current.forEach((section) => observer.unobserve(section));
};
}, [isInView, sectionsUpdated]);

return (
<div css={frameContainer}>
<Frame1 />
<Frame2 />
<Frame3 />
<Frame4 />
<Frame5 />
<Frame1 isInView={isInView[0]} refCallback={refCallback} />
<Frame2 isInView={isInView[1]} refCallback={refCallback} />
<Frame3 isInView={isInView[2]} refCallback={refCallback} />
<Frame4 isInView={isInView[3]} refCallback={refCallback} />
<Frame5 isInView={isInView[4]} refCallback={refCallback} />
<Frame6 />
<OnboardingFooter />
</div>
Expand Down