# 목표
Intro 파트는 왜 굳이 이런 컨셉을 했는지 설명하는 페이지이다.
따라서 내가 왜 welcome page에 혜성 애니메이션까지 넣어가면서 이 페이지를 준비했는지를 내가 어떤 사람인지와 연결시켜서 설명하는 것이 목적이다.
따라서 3가지 이유를 들어 내가 왜 혜성과 연결되는지를 설명할 것이다.
# 요구사항
1. 첫 화면은 welcome 화면과 자연스레 이어지도록 검은 화면에 제목 텍스트가 서서히 등장하도록 할 것
2. 3가지 요소를 스크롤에 따라 순차적으로 보여줄 것
아래 그림과 같이 스크롤에 따라 하나씩 콘텐트가 올라왔으면 한다.
# 설계
요구사항 1.
일단은 그냥 텍스트만 넣고 본다.
추후 적당한 폰트를 찾으면 welcome page의 타이핑 효과 넣을 때 같이 넣을 생각이다.
요구사항 2.
요구사항은 가로 방향으로 화면을 삼분할하여 적당한 배경 이미지와 함께 보여줄 생각이다.
따라서 flex를 쓸까 생각을 해보았지만, '순차적으로'가 문제이다.
flex를 사용하면 세 가지 요소가 동시에 나타날 것이다.
따라서 요소 하나 하나에 대한 div를 따로 만들고 이를 수직으로 배치한 뒤 position: sticky를 사용해 마지막 컨텐츠가 다 올라오면 화면을 다 채우는 방식을 사용할 것이다.
+ 추가 사항
제목 텍스트는 처음에는 화면 가운데 있다가 컨텐츠가 올라옴에 따라 위로 이동하게 구현하면 좋을 것 같다.
또한 각각의 컨텐츠도 올라올 때 서서히 나타나는 애니메이션을 적용하고 싶다.
그리고 컨텐츠 내부의 텍스트도 특정 스크롤 위치에 다다르면 변경해주고 싶다.
따라서 intersection api를 사용한다.
직접 scroll event를 받아서 할 수도 있겠지만, 이럴 경우 event가 너무 과도하게 발생할 가능성이 크다.
# 구현
HTML
전체적인 html은 다음과 같이 작성하였다.
introWrapper는 IntroComponent 전체를 감싸는 div의 크기를 설정하기 위한 클래스이다.
'혜성'이라는 타이틀을 추가하였고 각각의 요소를 stickyWrapper class의 div로 작성하였다.
마지막에는 몇 개의 bottomPlaceHolder를 넣어놨는데, 이것은 sticky content가 모두 보여진 후 content 내용 일부를 수정하기 위한 threshold로 사용하기 위한 용도 및 IntroComponent의 다음 element가 보여질 때 sticky가 적절히 화면에서 사라지게 하기 위한 용도로 넣어놨다.
(빈 div를 저렇게 넣어놓는건 구조적으로 마음에 들진 않는다. 근데 다른 방법이 생각이 안나서 일단 저렇게 해두었다.)
stickyWrapper는 말 그대로 position: sticky를 적용하기 위함이며 그 내부 구조는 다음과 같다.
여기서 <p>를 두 개 넣어놨는데, 위 쪽 <p>가 default로 보여줄 문장, 아래쪽이 일정 스크롤 후 보여줄 문장이다.
Script
Intro part에서 스크립트로 처리할 내용은 전부 intersection observer 관련 내용이다.
하나의 사례만 설명한 후, 나머지는 언제나와 같이 GitHub을 참고하라는 말만 남겨놓도록 하겠다.
아래 코드는 타이틀의 폰트 사이즈를 변경하기 위한 코드이다.
Title과 content의 background image에 해당하는 HTMLElement를 이용하여 첫 번째 background가 30% 이상 나타나면 글자 크기를 줄여준다.
Callback function인 'changeTitleSize'에 폰트 크기 변경을 위한 코드를 작성하였다.
그 후 IntersectionObserver를 생성하여 callback function과 '30%'이상을 나타내는 'threshold: 0.3' 옵션을 전달하고 첫 번째 background를 observing하도록 하였다.
Intersection api는 callback과 option이 필요하며 자세한 사항은 아래 링크를 참고하자.
https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
function observeTitle() {
const introTitle = document.getElementById('introTitle');
const firstBackground = document
.getElementsByClassName(styles.background)
.item(0);
// undefined check
if (!introTitle || !firstBackground) return;
// callback for observer
const changeTitleSize = (
entries: IntersectionObserverEntry[],
_observer: IntersectionObserver
) => {
entries.forEach((entry) => {
if (entry.target !== firstBackground) return;
if (entry.isIntersecting) introTitle.style.fontSize = '5vh';
else introTitle.style.fontSize = '10vh';
});
};
const observer = new IntersectionObserver(changeTitleSize, {
threshold: 0.3,
});
observer.observe(firstBackground);
}
# 결과
끝!
GitHub
https://github.com/dev-wann/portfolio
'Projects > Portfolio' 카테고리의 다른 글
Next.js 포트폴리오 페이지 제작기 - 5. Projects part (0) | 2023.08.05 |
---|---|
Next.js 포트폴리오 페이지 제작기 - 4. About part (0) | 2023.08.04 |
Next.js 포트폴리오 페이지 제작기 - 2. Welcome to Intro (0) | 2023.07.28 |
Next.js 포트폴리오 페이지 제작기 - 1. Welcome page 가구현 (0) | 2023.07.25 |
Next.js 포트폴리오 페이지 제작기 - 0. 프로젝트 구상 (0) | 2023.07.25 |