🐈‍⬛

SVGのオブジェクトをアニメーションで描く

2024/07/14に公開
2

はじめに

最近のwebページにはSVGがよく使われており、文字を描くアニメーションやオブジェクトを変形させるなど見かけます。今回はオブジェクトをアニメーションで描いてみます。
主にCSSを使い表現することができます。

そもそもsvgとは?

PNGやJPEGはラスター画像(ビットマップ画像)でピクセルの集合で画像を表現しますが、SVGはベクター画像で数式と座標で図形を描画します。そのため色々なメリットがあります。

利点
-高品質:画質を損なうことなくどのようなサイズにも拡大縮小可能。
-柔軟性:HTMLとCSSでスタイルを指定でき、JavaScriptを使用して操作できる。
-軽量化:ファイルサイズが軽量。

実装開始

データの準備

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

用意したイラストはこちら。
fill="none"で塗りはなく、 stroke="black"で黒の枠線で描いています。

SVGコードだとこちら。pathタグに"catPath"とクラス名を付けます。

index.html
 <svg width="202" height="168" viewBox="0 0 202 168" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path class="catPath"
   d="M21.5549 47.4417C21.5549 45.4417 18.5549 42.3834 20.0549 41.4417C21.5549 40.5 25.5549 44.9417 25.5549 44.9417C27.7216 48.4417 33.0549 55.9417 37.0549 57.9417C42.0549 60.4417 48.0549 63.4417 60.0549 63.9417C72.0549 64.4417 88.5549 59.4417 105.555 57.9417C119.155 56.7416 142.222 64.1083 152.055 67.9417C184.055 67.9417 185.555 50.9417 190.055 37.9417C193.655 27.5417 187.888 12.9417 184.555 6.94165C183.888 5.44167 183.255 2.24172 186.055 1.44172C188.855 0.641721 191.222 1.10839 192.055 1.44172C194.888 5.10839 200.555 17.1417 200.555 35.9417C200.555 59.4417 178.555 76.4417 178.555 79.4417C178.555 82.4417 181.555 85 181.555 88.9417C181.555 95.5 178.555 102.442 180.055 107.942C181.555 113.442 197.555 118.942 198.555 120.442C199.555 121.942 199.055 125.942 197.555 126.442C196.055 126.942 192.555 156.442 192.055 158.942C191.555 161.442 189.555 163.942 187.055 163.942C185.055 163.942 183.222 161.608 182.555 160.442C182.722 159.442 183.355 157.442 184.555 157.442C186.055 157.442 186.055 135.442 186.055 133.442C186.055 131.442 182.555 130.942 181.555 130.942C180.555 130.942 172.555 130.942 173.055 131.942C173.555 132.942 174.055 135.942 174.055 137.942C174.055 139.942 169.055 146.442 166.055 151.942C163.055 157.442 155.055 162.942 154.055 162.942C153.055 162.942 147.555 162.942 146.055 162.442C144.555 161.942 143.055 158.942 143.055 157.442C143.055 155.942 146.055 153.442 147.555 153.442C149.055 153.442 150.555 154.442 152.055 154.442C153.555 154.442 157.555 148.442 157.555 142.942C157.555 137.442 141.555 127.942 140.555 127.442C139.555 126.942 132.555 118.942 131.555 117.942C130.555 116.942 124.055 117.942 120.055 117.942C116.055 117.942 112.055 114.942 105.555 112.942C99.0549 110.942 97.5549 114.942 96.0549 114.942C94.5549 114.942 101.055 140.442 102.055 143.442C102.855 145.842 103.055 153.108 103.055 156.442C102.055 159.942 99.7549 166.942 98.5549 166.942H90.5549C89.0549 166.942 86.0549 164.942 86.0549 162.942C86.0549 161.342 87.0549 160.608 87.5549 160.442C89.5549 161.442 93.5549 152.942 94.0549 150.942C94.4549 149.342 81.2216 130.942 74.5549 121.942H73.0549C71.0549 120.942 36.0549 162.942 33.5549 163.942C31.0549 164.942 21.5549 164.442 20.0549 163.942C18.5549 163.442 17.0549 161.442 17.0549 160.442C17.0549 159.442 18.5549 157.442 20.0549 156.442C21.5549 155.442 23.0549 156.942 29.5549 156.442C36.0549 155.942 46.5549 122.942 46.5549 120.442C46.5549 117.942 42.5549 98.9417 42.0549 96.4417C41.5549 93.9417 32.5549 87.9417 30.5549 86.4417C28.5549 84.9417 23.0549 83.4417 20.0549 82.4417C17.0549 81.4417 9.55493 83.4417 8.55493 83.4417C7.55493 83.4417 4.05493 80.9417 2.55493 79.4417C1.05493 77.9417 1.55492 74.9417 1.05492 73.9417C0.554921 72.9417 3.55492 70.4417 6.55492 66.9417C9.55492 63.4417 8.05492 61.9417 10.5549 59.4417C12.5549 57.4417 17.7216 54.9417 20.0549 53.9417C20.5549 52.6084 21.5549 49.4417 21.5549 47.4417Z"
  fill="none" stroke="black" />
 </svg>

オブジェクト全体の線の長さを取得

"catPath"に対してgetTotalLength()メソッドを使用します。この線の長さを使い、後にcssでアニメーションさせます。今回の結果は995pxでした。

main.js
// オブジェクト要素
const catPath = document.querySelector('.catPath');
// オブジェクト要素の線の長さ
const strokeLength = catPath.getTotalLength();
/* 結果:995px */

CSSでアニメーション

ここで大事なのが、stroke-dasharrayとstroke-dashoffsetです。
stroke-dasharrayは、線の実線部分と空白部分の長さを指定するためのもので、線が点線や破線のように見えるように設定できます。

例えば

style.scss
 .catPath {
    stroke-dasharray: 20px;
  }

とすれば

指定したpxごとに実線部分と空白部分が交互に表示され、線のように見えます。

stroke-dashoffsetは、stroke-dasharrayで定義されたパターンの開始位置を指定するためのものです。これにより、線の描画をずらすことができます。

style.scss
 .catPath {
    stroke-dasharray: 20px;
    stroke-dashoffset: 20px; /* 追加 */
  }

とすれば

わかりにくいですが、よく見ると指定したpx分、線がずれて表示されます。

仕組みがわかったところで、まずはstroke-dasharrayに線の長さをそのまま指定します。そうすると、線の長さと破線の間隔が同じになり、見た目は破線ではなく、ただの直線のようになります。

style.scss
 .catPath {
    stroke-dasharray: 995px;
  }

とすれば

そこにstroke-dashoffsetに対しても線の長さを指定します。

style.scss
.catPath {
    stroke-dasharray: 995px;
    stroke-dashoffset: 995px;/* 追加 */
  }

とすれば


開始位置も線の長さだけズレており、画面には何も描かれていないように見えます(※グレーの線は実際には見えません)。

そしてstroke-dashoffsetを元の長さから0にアニメーションさせることで、線が描かれるように見えます。

style.scss
.catPath {
    stroke-dasharray: 995px;
    stroke-dashoffset: 995px;
    animation: drawLine 3s forwards; /* 追加 */
  }
  
  // 追加
  @keyframes drawLine {
    0% {
      stroke-dashoffset: 995px;
      fill: none;
    } 100% {
      stroke-dashoffset: 0;
    }
  }

とすれば

オブジェクトがアニメーションで描かれます
(ここではGIFファイルなのでアニメーションがカクついていますが、実際はもっとスムーズな動きです)。

さいごに

webサイトにオリジナルなアニメーションを付け加えることによって見た目がリッチになり、オリジナリティが増します。
こうした工夫で他のサイトと差別化を図っていきたいですね。
ぜひお試しください!

Discussion

nap5nap5

ぜひお試しください!

Reactでちょっとチャレンジしてみました

perokichiperokichi

おぉ〜、ありがとうございます。
とてもいい感じですね!