SVGアニメーションの作り方(stroke編)



下記のようなSVGアニメーションを実装してみたので書き残しておきます。




*参考



*環境

  • MacOS
  • CSS3
  • nuxt 2.8.1


*SVGとは

JPEG や PNG といったマップデータとは異なり、SVG は XML をベースにした 2次元ベクターデータと呼ばれる画像フォーマットのことです。ベクターデータは点の座標など数値データで構成されているため、CSS や Javascript を使ってその数値を変化させることで幅広いアニメーション表現をすることが可能になりました。


*SVGファイルの作成

Illustrator といったイラストソフトを使って画像を用意します。PNGファイルなどしか取得できない場合は、無料変換ツール Picsvg を使ってSVGファイルに変換することができます。(他にも無料で使えるツールがあるので好きなものを使ってください)


*コンポーネントの作成

今回は Nuxt.js で使う実装をしてみました。Nuxt.js プロジェクトでSVGを扱う場合は、コンポーネントとして切り出して使うことをおススメします。
<template />のなかにSVGファイルの中身<svg .../>を貼り付けます。今回はアニメーションを付けているので<path />にCSS クラスaを付与し、animationプロパティで動きを付けています。SVG ファイルのタグについては後述します。
<components/Logo.vue>
<template>
  <svg
    version="1.0"
    xmlns="http://www.w3.org/2000/svg"
    height="600pt"
    viewBox="0 0 600 200"
    preserveAspectRatio="xMidYMid meet"
  >
    <g transform="translate(0,400.000000) scale(0.1,-0.1)" fill="none">
      <path
        class="a"
        d="M3374 3067 c-3 -8 -4 -34 -2 -58 2 -36 7 -44 23 -44 18 0 20 7 20 55
  0 44 -3 55 -18 58 -9 2 -20 -3 -23 -11z"
      />
      <path
        class="a"
        d="M3794 3046 c-16 -12 -20 -31 -24 -133 -7 -148 -4 -163 25 -163 26 0
  38 24 34 68 -4 36 7 52 35 52 35 0 86 57 86 96 0 66 -102 119 -156 80z m84
  -52 c27 -19 28 -38 2 -64 -34 -34 -50 -26 -50 23 0 60 9 68 48 41z"
      />
      <path
        class="a"
        d="M4572 3037 c-12 -13 -22 -33 -22 -45 0 -11 -11 -32 -25 -46 -31 -31
  -31 -34 -2 -45 22 -8 23 -14 19 -70 -5 -71 3 -111 23 -111 19 0 27 30 25 98
  -2 81 -2 82 19 82 24 0 45 25 37 45 -3 8 -14 15 -25 15 -44 0 -24 39 27 55 36
  11 24 39 -18 43 -27 2 -41 -3 -58 -21z"
      />
      <path
        class="a"
        d="M4897 3053 c-2 -4 -4 -74 -4 -155 l0 -148 23 0 c26 0 25 -10 29 268
  0 30 -4 38 -22 40 -11 2 -23 0 -26 -5z"
      />
      <path
        class="a"
        d="M2528 3038 c-9 -8 -18 -36 -21 -67 -4 -29 -10 -58 -15 -65 -5 -6 -15
  -39 -22 -74 -12 -57 -11 -65 4 -80 16 -16 18 -16 32 2 8 11 14 36 14 56 0 43
  28 89 41 69 5 -8 9 -31 9 -52 0 -48 15 -77 39 -77 18 0 34 40 51 123 3 15 9
  29 14 30 10 2 35 -83 36 -119 0 -27 21 -46 39 -35 13 8 8 45 -18 146 -6 22
  -11 60 -11 85 0 49 -13 70 -41 70 -13 0 -19 -12 -24 -42 -12 -72 -31 -139 -40
  -141 -11 -3 -33 61 -34 100 -1 37 -17 83 -29 83 -4 0 -15 -6 -24 -12z"
      />
      <path
        class="a"
        d="M4995 3030 c-9 -27 10 -49 36 -43 27 7 32 19 17 43 -16 26 -45 26
  -53 0z"
      />
      <path
        class="a"
        d="M4370 2996 c0 -13 -10 -30 -22 -39 l-23 -15 26 -26 c25 -23 26 -29
  22 -89 -5 -59 -4 -66 16 -77 39 -20 54 3 46 71 -8 72 -1 95 31 103 31 8 27 28
  -7 36 -17 4 -25 14 -27 33 -3 22 -8 27 -33 27 -24 0 -29 -4 -29 -24z"
      />
      <path
        class="a"
        d="M3560 2968 c-47 -13 -70 -36 -70 -69 0 -32 31 -59 67 -59 14 0 23 -6
  23 -15 0 -22 -23 -28 -64 -17 -47 14 -65 -5 -37 -39 15 -19 29 -24 64 -24 60
  0 89 26 85 74 -2 29 -9 39 -35 51 -18 8 -33 23 -33 33 0 20 13 22 40 5 16 -10
  22 -10 34 2 13 12 13 19 3 40 -14 29 -29 32 -77 18z"
      />
      <path
        class="a"
        d="M3221 2957 c-43 -22 -66 -64 -65 -118 1 -62 27 -93 76 -91 92 5 103
  7 99 22 -2 8 -6 50 -9 92 -2 43 -10 82 -16 86 -21 17 -61 21 -85 9z m43 -63
  c16 -41 3 -94 -23 -94 -40 0 -55 57 -24 92 20 22 39 23 47 2z"
      />
      <path
        class="a"
        d="M4245 2962 c-11 -2 -25 -8 -32 -14 -7 -6 -14 -5 -18 2 -3 5 -12 10
  -20 10 -19 0 -27 -189 -8 -210 22 -24 38 4 35 61 -1 28 3 59 8 70 13 23 43 25
  60 4 23 -28 40 -18 40 23 0 31 -5 41 -22 48 -13 6 -32 8 -43 6z"
      />
      <path
        class="a"
        d="M5145 2960 c-38 -15 -58 -48 -63 -105 -4 -50 -2 -57 26 -85 39 -39
  66 -38 108 4 30 30 34 41 34 84 0 38 -5 55 -23 74 -28 30 -55 40 -82 28z m53
  -98 c6 -57 -60 -80 -74 -27 -9 36 13 67 44 63 23 -2 28 -9 30 -36z"
      />
      <path
        class="a"
        d="M2807 2932 c-23 -24 -27 -37 -27 -88 0 -81 14 -94 104 -94 l68 0 -7
  28 c-4 15 -8 58 -11 96 -4 77 -11 86 -65 86 -26 0 -42 -7 -62 -28z m81 -72 c2
  -36 -1 -47 -18 -58 -17 -10 -23 -9 -40 8 -25 25 -25 41 1 74 31 40 53 30 57
  -24z"
      />
      <path
        class="a"
        d="M2953 2943 c-4 -9 0 -28 8 -42 8 -14 26 -45 39 -68 l24 -43 -22 -44
  c-26 -51 -28 -84 -6 -93 18 -7 53 31 54 58 0 18 68 179 81 194 17 18 10 55
  -10 55 -24 0 -37 -17 -45 -57 -6 -25 -33 -52 -41 -41 -1 2 -12 24 -24 51 -23
  48 -47 60 -58 30z"
      />
      <path
        class="a"
        d="M4005 2942 c-11 -9 -29 -36 -39 -60 -19 -42 -19 -43 0 -80 38 -71
  104 -76 144 -10 26 42 25 92 -1 134 -16 27 -27 34 -52 34 -18 -1 -41 -8 -52
  -18z m85 -88 c0 -8 -9 -23 -20 -34 -16 -16 -25 -18 -40 -10 -32 17 -25 80 10
  92 16 7 50 -26 50 -48z"
      />
      <path
        class="a"
        d="M4713 2935 c-36 -41 -46 -86 -29 -127 31 -72 90 -84 138 -28 35 42
  37 97 7 146 -17 29 -26 34 -57 34 -27 0 -43 -7 -59 -25z m91 -89 c-16 -53 -74
  -52 -74 2 0 31 9 47 30 54 22 8 52 -30 44 -56z"
      />
      <path
        class="a"
        d="M4996 2944 c-3 -9 -6 -49 -6 -89 0 -40 3 -80 6 -89 8 -20 34 -21 35
  -1 5 51 6 163 2 178 -5 21 -29 22 -37 1z"
      />
    </g>
  </svg>
</template>
<style scoped lang="scss">
svg .a {
  stroke: $color-light-pink;
  stroke-miterlimit: 10;
  stroke-dasharray: 1000;
  stroke-dashoffset: 0;
  animation: stroke-reveal 2s ease infinite;
}

@keyframes stroke-reveal {
  from {
    stroke-dashoffset: 250;
    fill: rgba(250, 205, 198, 0);
    stroke-width: 1cm;
    stroke-opacity: 0.6;
  }
  to {
    stroke-dashoffset: 0;
    fill: rgba(250, 205, 198, 1);
    stroke-width: 0;
    stroke-opacity: 0;
  }
}
</style>

ページ全体を表示するコンポーネントで、先ほど作成したSVGのコンポーネントを呼び出します。
<pages/index.vue>
<template>
  <div>
 <div class="title-opening">
   <logo id="title"></logo>
    </div>
 ...
  </div>
</template>

<script>
import Logo from '~/components/Logo'
export default {
  components: {
    Logo
  },
  ...
</script>

<style  scoped  lang="scss">
svg {
  position: absolute;
  top: 0;
  right: 50vw;
  bottom: 0;
  left: 0;
  margin: auto;
  width: 75%;
}
...
</style>


*SVGタグ

このタグで囲むとSVGファイルになります。SVGタグに指定できるプロパティは下記になります。
  • width / height
    ブラウザ上の実際の表示幅と高さを指定します。

  • viewBox
    相対的なサイズを指定します。SVGタグにviewBox="0 0 600 200"と指定することができ、それぞれx座標の位置, y座標の位置, 描画エリアの幅(座標値), 描画エリアの高さ(座標値)のサイズになります。

  • preserveAspectRatio
    xMinYMin meetを指定することで、縦横比を変えないようにすることができます。noneにするとviewBoxの値によって画像が横長や縦長になったりします。


*Gタグ

オブジェクトをグループ化するためのコンテナ要素です。
  • transform
    変形や移動の指定をすることができます。translate(x, y)で座標値への移動、scale(sx, sy)で拡大縮小を設定することができます。

  • fill
    塗る色を指定することができます。blueまたは#FF4433のコード値を設定します。noneにすると色が塗られません。


*PATHタグ

d属性を指定することで線を描画することができます。Mで始点の座標を指定し、そのあと順番の座標に線を引いていきます。


*CSS

  • stroke
    オブジェクトの縁の色を指定します。

  • stroke-width
    オブジェクトの縁の幅を指定します。

  • stroke-opacity
    オブジェクトの縁の不透明度を指定します。

  • stroke-miterlimit
    どこで描画を止めるかを指定することができます。

  • stroke-dasharray
    点線の長さパターンを指定することができます。
    値を大きくすることで波線を描画することができます。カンマ区切りの数値を指定すると、それぞれストロークで塗りつぶす領域の長さ、および塗りつぶさないエリアの長さになります。

  • stroke-dashoffset
    波線をどこから始めるか指定することができます。stroke-dasharrayと一緒に使います。


*所感

SVGアニメーションを作成できる無料ジェネレーターなども見つけたので、簡単なものはコピペするだけで実現できてしまうかもしれません。どの場面でどのエフェクトを使うとユーザー体験が良くなるかといったことをよく考慮し、効果的なアニメーションを実装できるようにしていこうと思います。


Previous
Next Post »

人気の投稿