gsap에서 제공되는 split text라는 기능이 있다.
하지만 그건 유료이기 때문에 split-type이라는 무료 플러그인을 사용해서 글자 쪼개기,
gsap를 활용해 애니메이션까지 구현해 볼 예정!
활용한 플러그인
<script src="https://unpkg.com/split-type"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
split-type과 gsap 플러그인 연결해주어야 한다.
로컬 파일로 저장해서 연결해도 ok
HTML 구조
<section>
<button onclick="playBtn()">Play Split Text!</button>
<p class="text">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nostrum
distinctio ad quo natus et animi facere suscipit fuga sed rem aliquam
exercitationem possimus non, ab enim illo dolore officia molestiae?
Eligendi doloribus voluptatibus in necessitatibus, porro corrupti fugiat
recusandae esse, provident ducimus ab iure ratione tenetur eius magni
accusantium temporibus incidunt magnam nesciunt ipsa molestiae placeat
facilis excepturi? Beatae reiciendis saepe eligendi quas est fugiat
repellat. Nisi, earum quod non dignissimos eaque reprehenderit fugiat
culpa corporis illum ullam error id totam, qui doloribus, quibusdam
ipsam eum! Odit, incidunt, quos id ipsam inventore qui molestias facere
pariatur perferendis unde beatae!
</p>
</section>
간단하게 section 안에 p태그를 작성해 로렌입숨 작성~
text라는 class를 붙여주었다.
그리고 난 버튼을 누르면 애니메이션이 재생되도록 button태그와 onclick속성을 사용함.
CSS
@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap");
* {
margin: 0;
padding: 0;
}
body {
overflow-x: hidden;
font-family: "Roboto";
}
section {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
gap: 50px 0;
align-items: center;
justify-content: center;
}
section p {
word-break: keep-all;
padding: 0 30px;
line-height: 30px;
font-size: 22px;
}
button {
border: 1px solid #000;
background: #fff;
padding: 10px;
border-radius: 20px;
cursor: pointer;
}
// 🥰🥰 overflow: hidden;
.line {
display: inline-block;
overflow: hidden;
}
딱히 css부분은 설명할 부분은 없지만,
신경써야할 부분이 있다.
바로 .line 부분인데 일단 스크립트 설명이 필요하다.
스크립트
function playBtn() {
let typeSplit = new SplitType(".text", {
types: "lines, words, chars",
tagName: "span",
});
gsap.from(".text .word", {
y: "100%",
opacity: 1,
duration: 0.3,
ease: "circ.out",
stagger: 0.1,
});
}
😍 글자 쪼개기
Split-type은 텍스트를 줄(lines), 단어(words), 그리고 글자(chars) 단위로 나누는 라이브러리이다.
- new SplitType(".text", {...})는 .text 클래스를 가진 요소 내의 텍스트를 각 줄, 단어, 글자 단위로 분리한다.
- tagName: "span" 옵션을 설정하면 각 줄, 단어, 글자가 <span> 태그로 감싸진다. 이 태그는 이후 애니메이션에서 각 텍스트 요소를 선택할 수 있게 해주는데, span이 아니고 다른 태그로 감싸기 가능(em, p, div 등등등..)
🤩 GSAP 애니메이션 주기
- gsap.from(...)는 애니메이션이 시작할 때의 상태를 설정하는 메서드. 여기서는 ".text .word" 선택자를 통해 .text 요소 내의 각 단어(.word 클래스로 감싸진 요소들)에 애니메이션을 적용
- y: "100%"는 각 단어가 애니메이션 시작 시 아래쪽으로 100% 위치에서 시작하도록 설정. 즉, 텍스트가 아래에서 위로 올라오는 효과가 나타난다.
- opacity: 1은 각 단어가 애니메이션 시작 시 불투명도가 1로 설정되어 있으며(투명도가 없도록 설정), 이를 통해 부드러운 전환 효과가 난다.
- ease: "circ.out"은 애니메이션의 속도 곡선을 정의하는데, circ.out은 빠르게 시작했다가 천천히 끝나는 원형의 속도 곡선으로, 자연스러운 움직임을 만든다. (다른 ease 효과도 많으니 참고!). https://gsap.com/docs/v3/Eases/
- stagger: 0.1은 각 단어가 0.1초 간격으로 순차적으로 애니메이션되도록 하여 하나씩 등장하는 효과를 준다.
해당 구조를 살펴보면
text 안에 line,
line 안에 word,
word 안에 char가 있는 걸 확인할 수 있다!
.line에 overflow: hidden을 준 이유? 🤔🤔
.line 요소에 overflow: hidden을 설정한 이유는 텍스트 애니메이션이 이동할 때 불필요하게 보이는 부분을 숨기기 위해서이다. 아래에서 위로 이동하는 애니메이션 중 텍스트가 화면 밖에 있는 동안 보이지 않게 하는 역할을 한다. word를 line이 감싸고 있기 때문에 .line에다 해당 속성을 준 것이다.
또한 span태그는 inline요소기 때문에 inline-block을 적용해 주어야한다. (태그에 따라 다르므로 참고.)
밑 예제는 overflow: hidden을 적용 시키지 않았을 때의 예제!
전체코드
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>test</title>
<style>
@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap");
* {
margin: 0;
padding: 0;
}
body {
overflow-x: hidden;
font-family: "Roboto";
}
section {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
gap: 50px 0;
align-items: center;
justify-content: center;
}
section p {
word-break: keep-all;
padding: 0 30px;
line-height: 30px;
font-size: 22px;
}
.line {
display: inline-block;
overflow: hidden;
}
button {
border: 1px solid #000;
background: #fff;
padding: 10px;
border-radius: 20px;
cursor: pointer;
}
</style>
</head>
<body>
<section>
<button onclick="playBtn()">Play Split Text!</button>
<p class="text">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Porro nostrum
distinctio ad quo natus et animi facere suscipit fuga sed rem aliquam
exercitationem possimus non, ab enim illo dolore officia molestiae?
Eligendi doloribus voluptatibus in necessitatibus, porro corrupti fugiat
recusandae esse, provident ducimus ab iure ratione tenetur eius magni
accusantium temporibus incidunt magnam nesciunt ipsa molestiae placeat
facilis excepturi? Beatae reiciendis saepe eligendi quas est fugiat
repellat. Nisi, earum quod non dignissimos eaque reprehenderit fugiat
culpa corporis illum ullam error id totam, qui doloribus, quibusdam
ipsam eum! Odit, incidunt, quos id ipsam inventore qui molestias facere
pariatur perferendis unde beatae!
</p>
</section>
</body>
<script src="https://unpkg.com/split-type"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script>
function playBtn() {
let typeSplit = new SplitType(".text", {
types: "lines, words, chars",
tagName: "span",
});
gsap.from(".text .word", {
y: "100%",
opacity: 1,
duration: 0.3,
ease: "circ.out",
stagger: 0.1,
});
}
</script>
</html>
해당 기능을 통해 스크롤 트리거까지 활용하면 훨씬 더 고급스러운 효과를 표현할 수 있다!