테두리부터 채워지는 글자 디자인 만들기

Project Diary/React + Firebase (Snack ShoppingMall)

글자가 테두리부터 채워지는 애니메이션 빙밥 기록


이 작업은 꽤 세밀한 조정이 필요한데요, 그래도 결과물보니까 뿌듯헸습니다. 특히, 애니메이션이 적용된 텍스트는 웹사이트의 인상을 확 높여줄 수 있습니다.

 

주요 기술:

  • CSS 애니메이션
  • SVG (Scalable Vector Graphics)
  • React와 styled-components

 

1.TextAnimation.js 파일을 생성해서 기본 컴포넌트를 작성

import React from 'react';
import styled, { keyframes } from 'styled-components';

const TextAnimationBlock = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #fff;
`;

const Text = styled.svg`
  font-size: 50px;
  font-weight: 600;
  fill: #5a4620;
  stroke: #5a4620;
  stroke-width: 0.75px;
  stroke-linecap: round;
  stroke-linejoin: round;
`;

const TextAnimation = () => {
  return (
    <TextAnimationBlock>
      <Text width="400" height="100" viewBox="0 0 400 100">
        <text x="50%" y="50%" dy=".3em" textAnchor="middle">
          쿠와자와 과자점
        </text>
      </Text>
    </TextAnimationBlock>
  );
};

export default TextAnimation;

 

 

2. SVG 텍스트 설정

SVG 텍스트를 설정해서 애니메이션을 적용할 준비를 해요. 이 부분에서는 SVG 텍스트의 기본 설정을 하고, 나중에 애니메이션을 추가합니다.

import React from 'react';
import styled from 'styled-components';

const TextAnimationBlock = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #fff;
`;

const Text = styled.svg`
  font-size: 50px;
  font-weight: 600;
  fill: #5a4620;
  stroke: #5a4620;
  stroke-width: 0.75px;
  stroke-linecap: round;
  stroke-linejoin: round;
`;

const TextAnimation = () => {
  return (
    <TextAnimationBlock>
      <Text width="400" height="100" viewBox="0 0 400 100">
        <text x="50%" y="50%" dy=".3em" textAnchor="middle">
          쿠와자와 과자점
        </text>
      </Text>
    </TextAnimationBlock>
  );
};

export default TextAnimation;

 


3. 애니메이션 적용

이제 애니메이션을 적용해보겠습니다. 애니메이션은 글자의 테두리가 그려지듯이 나타나고, 그 후에 채워지도록 만들 거예요. 꽤 장황한 코드가 되더라구요.

import React from 'react';
import styled, { keyframes } from 'styled-components';

// 테두리 애니메이션
const strokeAnimation = keyframes`
  0% {
    stroke-dasharray: 400;
    stroke-dashoffset: 400;
  }
  100% {
    stroke-dashoffset: 0;
  }
`;

// 채우기 애니메이션
const fillAnimation = keyframes`
  0% {
    fill-opacity: 0;
  }
  100% {
    fill-opacity: 1;
  }
`;

const TextAnimationBlock = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #fff;
`;

const Text = styled.svg`
  font-size: 50px;
  font-weight: 600;
  fill: #5a4620;
  stroke: #5a4620;
  stroke-width: 0.75px;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: ${strokeAnimation} 2s ease forwards, ${fillAnimation} 4s ease forwards 2s;
`;

const TextAnimation = () => {
  return (
    <TextAnimationBlock>
      <Text width="400" height="100" viewBox="0 0 400 100">
        <text x="50%" y="50%" dy=".3em" textAnchor="middle">
          쿠와자와 과자점
        </text>
      </Text>
    </TextAnimationBlock>
  );
};

export default TextAnimation;

 

 

4. 애니메이션 조정 및 테스트

애니메이션 속도와 타이밍을 조정해보아요. 애니메이션이 자연스럽게 보이도록 다양한 값을 시도해보세요.

import React from 'react';
import styled, { keyframes } from 'styled-components';

// 테두리 애니메이션
const strokeAnimation = keyframes`
  0% {
    stroke-dasharray: 400;
    stroke-dashoffset: 400;
  }
  100% {
    stroke-dashoffset: 0;
  }
`;

// 채우기 애니메이션
const fillAnimation = keyframes`
  0% {
    fill-opacity: 0;
  }
  100% {
    fill-opacity: 1;
  }
`;

const TextAnimationBlock = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #fff;
`;

const Text = styled.svg`
  font-size: 50px;
  font-weight: 600;
  fill: #5a4620;
  stroke: #5a4620;
  stroke-width: 0.75px;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: ${strokeAnimation} 2s ease forwards, ${fillAnimation} 4s ease forwards 2s;
`;

const TextAnimation = () => {
  return (
    <TextAnimationBlock>
      <Text width="400" height="100" viewBox="0 0 400 100">
        <text x="50%" y="50%" dy=".3em" textAnchor="middle">
          쿠와자와 과자점
        </text>
      </Text>
    </TextAnimationBlock>
  );
};

export default TextAnimation;