TIL - 타이핑 애니메이션

정길웅·2024년 1월 30일

TIL

목록 보기
2/9

타이핑 애니메이션은 커스텀 훅과 tailwind로 작성하였다.

1. 커서 '|' 깜빡거림

커서의 깜빡거림은 blink라는 keyframe을 작성하여 opacity가 0이 되도록 하였다. 이를 tailwind.config.ts에 표현하면 다음과 같다.

import type { Config } from 'tailwindcss';

const config: Config = {
	content: [
		'./pages/**/*.{js,ts,jsx,tsx,mdx}',
		'./components/**/*.{js,ts,jsx,tsx,mdx}',
		'./app/**/*.{js,ts,jsx,tsx,mdx}',
	],
	theme: {
		extend: {
			keyframes: {
				blink: {
					to: { opacity: '0' },
				},
			},
			animation: {
				typing: 'blink 1s infinite',
			},
		},
	},
};
export default config;

이렇게 무한대로 깜빡이는 커서를 완성했다.

2. 타이핑 애니메이션

타이핑이 동작하는 방식은 1.타이핑 될 글자와 타이핑 된 글자의 길이를 비교하기 2.타이핑 될 글자를 x초마다 입력하고 타이핑 될 글자가 완성되면 타이핑 중단하기로 구성되어있다.
검색해보니 setInterval이라는 함수를 사용하기에 공부하고 따라썼다.

import { useState, useEffect } from 'react';

/**
 * @param startTime : 이벤트 시작 타이밍
 * @param content : 타이핑 될 글
 * @returns text : 타이핑 되어가는 글자
 * @returns isEnd : 타이핑이 끝났다는 신호
 */
function useTyping(content: string) {
	const [text, setText] = useState('');
	const [characterCount, setCharacterCount] = useState(0);
	const [isEnd, setIsEnd] = useState(false);

	useEffect(() => {
		const typeEvent = setInterval(() => {
			setCharacterCount((prev) => prev + 1);
			setText((prev) => prev + content[characterCount]);
		}, 100);

		if (text.length > content.length - 1) {
			setIsEnd(true);
			clearInterval(typeEvent);
		}

		return () => clearInterval(typeEvent);
	}, [text, isEnd]);
	return { text, isEnd };
}

export default useTyping;

이렇게 0.1초당 한 글자씩 타이핑이 나가는 커스텀 훅이 완성되었다. 총 정리해서, 이를 사용하는 방식은

1. const { text, isEnd } = useTyping(string변수)
2. <span className ={`${isEnd ? 'hidden' : 'animate-typing'}`}>|<span>

를 사용하여 text와 animate-typing 클래스를 활용하는 것이다.
최종적인 코드는 이런식으로 나왔다.

'use client';

import useTyping from '@/app/utils/typingAnimation';

const About01 = () => {
	const subTitle =
		'현실같은 가상 공간과 증강현실로 연결된 메타버스 플랫폼을 만드는 기업';
	const { text, isEnd } = useTyping(subTitle);
	return (
		<div className='w-full text-center text-white'>
			<div className='mb-9 text-mobilebase sm:mb-10 sm:text-2xl'>
				{text}
				<span className={`${isEnd ? 'hidden' : 'animate-typing'} `}>|</span>
			</div>
			<div className='text-6xl font-bold '>WOORIRIWOO</div>
		</div>
	);
};

export default About01;

profile
사람들과 소통하는 FE 개발자입니다

0개의 댓글