🎨

SVGを使った文字のアニメーションエフェクト

2024/07/17に公開

はじめに

今回はSVGで作った文字をアニメーションで色を変えてみます。CSSのみで実装可能です。
出来上がりはこちら。

主に対象要素に対してクリッピングパス(切り抜き)を使用して実現しています。

実装開始

データの準備

今回、Figmaで文字を作成してSVGファイルとして保存しました。これを使ってアニメーションを実現させます。

用意した文字はこちら。

HTML

index.html
    <div class="container">
    <div class="clip-path-wrapper">
      <div class="clipped-bg"></div>
      <svg class="text-svg" width="310" height="78" viewBox="0 0 310 78" fill="none" xmlns="http://www.w3.org/2000/svg">
        <defs>
          <clipPath id="clip-Path">
            <!-- W -->
            <path
              d="M55.411 45.548L34.4667 1H73.165L89.3303 31.9726L89.993 33.2422L90.9566 32.1828L94.7156 28.0504L95.2029 27.5147L94.846 26.8847L80.1855 1H116V28.4437H107.602H106.898L106.661 29.1066L89.5127 77H69.219L59.6284 57.9217L58.5498 55.7762L57.7868 58.0531L51.4371 77H30.7275L9.84455 29.0445L9.58295 28.4437H8.92771H1V1H26.1504L49.3734 50.0176L49.9332 51.1992L50.927 50.3494L55.1559 46.7336L55.7354 46.2381L55.411 45.548Z"
              stroke="black" stroke-width="2" />

            <!-- E -->
            <path
              d="M137.421 29.9178V28.9178H136.421H127V1H213V36.3973H200.6L194.891 28.9073L194.59 28.5135H194.095H182.737H181.737V29.5135V30.9863V31.9863H182.737H189.842V45.4819H182.737H181.737V46.4819V48.0822V49.0822H182.737H193.158H193.594L193.891 48.7628L200.541 41.6027H213V77H127V49.0822H136.421H137.421V48.0822V29.9178Z"
              stroke="black" stroke-width="2" />

            <!-- B -->
            <path
              d="M288 75H224V48.5H232.5H233.5V47.5V29V28H232.5H224V1H288C294.311 1 299.083 2.79358 302.313 5.6492C305.538 8.50094 307.311 12.485 307.501 17.0416C307.697 21.746 307.166 26.4184 306.479 30.1699C305.789 33.9386 304.954 36.7097 304.577 37.6154L304.401 38.0379L304.606 38.4472C307.221 43.6781 310.44 53.0704 307.538 63.2253C306.072 68.3581 304.18 71.1908 301.318 72.8182C298.382 74.4878 294.25 75 288 75Z"
              stroke="black" stroke-width="2" />
            <path d="M275.5 34H271V18H275.5V34Z" stroke="black" stroke-width="2" />
            <path class="" d="M275.5 58H271V42H275.5V58Z" stroke="black" stroke-width="2" />
          </clipPath>
        </defs>
      </svg>
    </div>

      <svg 
      class="initial-text-svg"
      width="310" height="78" viewBox="0 0 310 78" fill="none" xmlns="http://www.w3.org/2000/svg">
      <!-- W -->
      <path
        d="M137.421 29.9178V28.9178H136.421H127V1H213V36.3973H200.6L194.891 28.9073L194.59 28.5135H194.095H182.737H181.737V29.5135V30.9863V31.9863H182.737H189.842V45.4819H182.737H181.737V46.4819V48.0822V49.0822H182.737H193.158H193.594L193.891 48.7628L200.541 41.6027H213V77H127V49.0822H136.421H137.421V48.0822V29.9178Z"
        stroke="black" stroke-width="2" />
      <!-- E -->
      <path
        d="M288 75H224V48.5H232.5H233.5V47.5V29V28H232.5H224V1H288C294.311 1 299.083 2.79358 302.313 5.6492C305.538 8.50094 307.311 12.485 307.501 17.0416C307.697 21.746 307.166 26.4184 306.479 30.1699C305.789 33.9386 304.954 36.7097 304.577 37.6154L304.401 38.0379L304.606 38.4472C307.221 43.6781 310.44 53.0704 307.538 63.2253C306.072 68.3581 304.18 71.1908 301.318 72.8182C298.382 74.4878 294.25 75 288 75Z"
        stroke="black" stroke-width="2" />
      
      <!-- B -->
      <path d="M275.5 34H271V18H275.5V34Z" fill="white" stroke="black" stroke-width="2" />
      <path class="" d="M275.5 58H271V42H275.5V58Z" fill="white" stroke="black" stroke-width="2" />
      <path
        d="M55.411 45.548L34.4667 1H73.165L89.3303 31.9726L89.993 33.2422L90.9566 32.1828L94.7156 28.0504L95.2029 27.5147L94.846 26.8847L80.1855 1H116V28.4437H107.602H106.898L106.661 29.1066L89.5127 77H69.219L59.6284 57.9217L58.5498 55.7762L57.7868 58.0531L51.4371 77H30.7275L9.84455 29.0445L9.58295 28.4437H8.92771H1V1H26.1504L49.3734 50.0176L49.9332 51.1992L50.927 50.3494L55.1559 46.7336L55.7354 46.2381L55.411 45.548Z"
        stroke="black" stroke-width="2" />
      </svg>
  </div>

要素の説明

<div class="clip-path-wrapper">
クリップパスを適用するためのラッパー要素です。CSSで表示させるサイズを指定します。

<div class="clipped-bg">
この要素は後で背景色がアニメーションで変わるように設定され、SVGの形状にクリップされます。

<svg class="text-svg">
このSVG要素の中に「WEB」という文字が<path>要素で入っています。

<clipPath id="clip-Path">
この要素は、クリップパスを定義します。特定の形状(ここでは「WEB」)に対してクリッピングを行います。

<svg class="initial-text-svg">
ここでは全く同じ形のSVGの文字をもう一つ用意しています。こちらは予め表示させておく黒縁白抜きの文字です。WEBという文字の「B」の中にある穴は後に塗り潰されないようにfill="white"にしています。

CSS

style.scss

.container {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;

  .clip-path-wrapper {
    position: relative;
    width: 310px;
    height: 78px;

    .clipped-bg {
      width: 100%;
      height: 100%;
      background: linear-gradient(90deg, rgba(0, 0, 0, 1) 50%, rgba(255, 255, 255, 1) 50.1%);
      background-size: 200% 100%;
      clip-path: url(#clip-Path);
      animation: changeTextColor 1.5s 1s forwards;
    }

    // 1つ目のSVG
    .text-svg {
      /* 何も指定せず */
    }

    @keyframes changeTextColor {
      0% {
        background-position: 100% 50%;
      }

      100% {
        background-position: 0% 50%;
      }
    }
  }

  // 2つ目のSVG
  .initial-text-svg {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}

スタイルの説明

.clip-path-wrapper
描画するサイズを指定します。

.clipped-bg
白と黒を半々にした背景を用意します。そのサイズの横幅を200%に拡大します。これをアニメーションでbackground-positionを動かします。またclip-path: url(#clip-Path)と指定することで<clipPath id="clip-Path">の要素の形状にクリップされます。

そうするとこのようなアニメーションができます。

これだと初めから文字が表示されていないので、<svg class="initial-text-svg">にある文字を予め表示させ、その真上でアニメーションさせることで初めに紹介した見た目にできます。
イメージだとこのようになります。

これで初めに紹介したアニメーションができます。

さいごに

SVGを使って文字をアニメーションできれば、例えばローディングの時に使用するなどしてキャッチーな印象を与えることもできます。

それにしてもSVGは奥が深いなと。その分いろんなことができると思うので、更に学んでいきたいです。

Discussion