SVGとCSSで作る手書き風テキストアニメ【前編】

アバター画像 fujii

4

こんにちは。エンジニアの藤井です。
さて、今日はSVGを動かして手書き風テキストアニメーションを作成します。

少し長くなりそうなので、2回に分けてレシピを紹介します。
前編ではアニメーションさせる画像を作成し、スタイルを整えるまでの下ごしらえをしましょう♪
後編は、アニメーションの仕組みと実装方法を紹介します。

完成形

See the Pen Handwriting text by knap_develp (@knap_develp) on CodePen.

さて、今回もKNAPの合言葉「Design trekking」を動かしました。
さらさらサラリと筆記体を書いていくアニメーション、かわいいですね。

実装は次の手順で進めます。
1. SVG画像を作成する(★)
2. CSSでスタイルを整える(★)
3. アニメーションを追加する

今回は1と2の手順を詳しくみていきましょう!

実装① SVG画像を作成する

アニメーションさせたいテキストの画像を作ります。
SVGで書き出しができるものであれば、デザインツールはなんでもOKです!

まずは、テキストツールで任意の文字を入力して、アウトライン化しましょう。
テキストは文字同士が繋がっている筆記体がおすすめです。

次に、新しいレイヤーに作成したテキストの上をなぞるパスラインを追加します。

この時に注意したいのは、下地になるテキストをしっかりと覆うようにすることと、アニメーションさせる書き順でパスを作成します。
色はCSSで指定するので、画像作成は分かりやすい色で作業するのがおすすめです◎

ここまでできたら、svg形式で画像を書き出しましょう。

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 648.98 117.44">
  <defs>
    <style>
      .cls-1 {
        stroke-width: 0px;
      }

      .cls-2 {
        fill: none;
        stroke: #000;
        stroke-miterlimit: 10;
        stroke-width: 7px;
      }
    </style>
  </defs>
  <g id="_レイヤー_1" data-name="レイヤー 1">
    <g>
      <path class="cls-1" d="m59.27,69.53c-6.5,2.8-13.5,4.3-20.6,4.5l-7.5.2c-2,.2-4,.3-6,.3s-8.2,0-8.2-3.2c0-2.7,1.7-2.7,3.8-3.6.9-.5,1.8-1,2.6-1.7,3.6-2.7,6-3.4,10.2-4.4,2.2-.5,6.2-17.5,6.8-20.1l1.8-7c.4-1.7,1.9-6.4,1.9-8,0-.1,0-.4-.1-.5-1.1-1.7-17-7.9-20.4-9.3-1.2-.5-7.1-3.4-8.4-3.4h-.5c-1.4,0-2.7-2.1-2.7-3.4s1.2-1.9,2.3-1.9c2.2,0,12.4,5,14.9,6.1,2.6,1.1,5.2,2.2,7.8,3.2,2,.8,6.5,3,8.1,3,1.4,0,1.5-2,3.5-2,1.7,0,1.9,1.3,1.9,2.5v1c0,1.1,1.6,1.9,2.3,2.4,8.5,5.6,22.1,15.6,22.1,26.8,0,9.7-7.3,15-15.6,18.5Zm3.8-30.8c-3.2-3.4-7.5-7.2-11.7-9.4-.6-.3-1.3-.7-2.1-.7-1.1,1-4.5,17.8-5.1,20.4-.4,2.2-1.6,5.5-1.6,7.7,0,.9.4,1.2,1.2,1.2,2,0,19.5-5,22.1-6,.4-.2.9-.4,1.4-.4s1,.3,1,.9c0,3.9-10,6.3-12.8,7.1-2.9.8-23.2,7.6-24.2,8.7-.2.3-.4.6-.4,1,0,.7,1.1.7,1.7.7,2.2,0,4.5-.6,6.7-.9,1.8-.2,3.6-.2,5.4-.4,3.8-.3,7.5-1.2,11.1-2.4,6.4-2,14-8,14-15.3,0-4.6-3.8-9-6.7-12.2Z"/>
~~~ 省略 ~~~
      <path class="cls-1" d="m640.76,64.33l-9.1,5.1c-2.3,1.2-8,5.8-8.5,8.4-.2.9-.2,2.1-.2,3.4-.2,12.6-1,25.5-7.2,31.4-1.6,1.6-4.1,2.9-6.5,2.9-5.1,0-6.5-5.5-6.5-9.7,0-3.1.5-6.2,1.3-9.1,1.2-3.9,2.7-7.6,4.8-11.1l2.8-4.1c1.1-1.5,5.2-6,5.4-7.7.2-1.5.3-3.1.3-4.6v-.4c0-.5,0-1.4-.3-1.4,0,0-7.4,3.9-11.7,3.9-3.6,0-4.6-2.1-4.6-5.4,0-5,4.3-8.9,7.3-12.4,4.2-4.8,10.7-11.1,15.8-15.1,1-.8,2.1-1.3,3.4-1.3,1.5,0,3.3.8,3.3,2.5,0,1.1-1.3,3.1-2.5,3.1,0,0-.2,0-.2.2,0,1.3,2.1,2.1,2.1,5.6,0,1.5-.7,3.1-1,4.5-.9,3.3-2.9,6.2-3.7,9.5-.4,1.8-1.5,3.6-1.5,5.5,0,.2,0,.6.3.6.2,0,6.6-3.6,7.3-3.9.5-.2,11.6-4.9,11.7-4.9.4,0,.6.6.6,1,0,1.6-1.6,2.8-2.9,3.5Zm-23.5,20.3v-.5c0-.2-.1-.3-.2-.3-1.4,0-5.9,8.2-6.5,9.4-.7,1.4-1.3,2.8-1.9,4.3-.7,2.2-1.4,4.5-1.4,6.8,0,1.2.1,6.4,2,6.4,1.6,0,3.8-3.3,4.6-4.4,3-4.5,3.5-11.8,3.5-17,0-1.6-.1-3.2-.1-4.7Zm5.3-37.6c-2.5,0-14.9,14.5-14.9,17.5,0,.9,1.4,1.2,2.1,1.2,2.3,0,5.9-3.4,7.5-4.9,3.4-3.1,5.7-8.3,5.8-12.9,0-.4,0-.9-.5-.9Z"/>
    </g>
  </g>
  <g id="_レイヤー_2" data-name="レイヤー 2">
    <path class="cls-2" d="m48.29,17.92l-12,50L6.65,8.89s70.26,19.16,65.26,44.16-53.74,18.67-53,18c3.33-3.01,50-19,50.5-19.5l6.45,14.48s27.55-13.48,21.55-21.48c-7.52-10.02-23,23-9,25,13.02,1.86,45-23.12,45-23.12,0,0-.89,28.68-22,18.12-.94-.47-2,7,21,4s31-23,31-23c0,0-13,21-5,26,1.95,1.22,17.09-1.77,22-11,14-43,34-25,34-25,0,0-36,23-28,33,0,0,23-2,21-25-1,4-3.25,6.79-6,28,0,26-4.16,44.93-11,42s-1.93-23.66,11-39c22-12,36-27,36-26s-10,20-7,22c4-2,20-17,21-15,1,3-6,11-1,14s28-9,28-9l22,6s17,1,35-41c7-12-27,40-12,43,30,0,33-28,33-28,0,0-2,15,8,8,2,2-11,16-1,22,11-2,42-14,34-27-15-1-19,24-8,26,18,1,66.59-30.97,46-53-15.41-4.97-27,54-15,60,0,0-5-16,26-38,19,4-20,22-20,22-1,3-1,9,13,10,15-1,63-23,48-54-18-2-23,53-15,60,0-10,22-41,29-38,11,9-19.78,19.55-21.39,21.28-1.61,3.72-1.61,8.72,7.39,9.72,21,5,44-21,41-22s-9,22-4,24c9,2,44-21,41-24-3,0-8,21-7,23,1,0,20-17,21-16,0,2-5,12-1,15,4,2,19-6,19-6,0,0,16-41,33-26,0,0-9.49,5.42-17,13-7,8-11,14-9,17,7,5,27-14,21-23,4,1-1.61,6.78-5,27,0,18,1.93,38.6-11.03,42.3-11.97-2.3,5.03-34.3,8.03-37.3s28-17,28-17l-2-52L158.4,3.55l9,17,141,12h68l150.13-16.03,16.89,7.3"/>
  </g>
</svg>

実装② CSSでスタイルを整える

書き出したsvgにclassを付与し、CSSでスタイルを整えます。
パスラインで下地のテキストをマスクするために、パスラインの<g>は<mask>に変更しておきましょう。
インラインで書かれているスタイルも削除します。

今回の例で指定したid, class, スタイルは次の通りです。
実際に描画する色は「.handwriting_text」に指定しましょう。

idclassスタイル
<svg>.handwriting
<g>#textmask: url(#mask);
.handwriting_textfill: #404040;
(描画色)
<mask>
パスライングループ
#mask.handwriting_mask
<path>
パスライン
.handwriting_mask_linefill: none;
stroke: #fff;
stroke-width: 7;
stroke-linecap: round;
stroke-linejoin: round;

整えたソースコード(html)

<?xml version="1.0" encoding="UTF-8"?>
<svg class="handwriting" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 648.98 117.44">
  <g id="text" class="handwriting_text" data-name="レイヤー 1">
    <g id="text-path" class="handwriting_text_path">
      <path class="cls-1" d="m59.27,69.53c-6.5,2.8-13.5,4.3-20.6,4.5l-7.5.2c-2,.2-4,.3-6,.3s-8.2,0-8.2-3.2c0-2.7,1.7-2.7,3.8-3.6.9-.5,1.8-1,2.6-1.7,3.6-2.7,6-3.4,10.2-4.4,2.2-.5,6.2-17.5,6.8-20.1l1.8-7c.4-1.7,1.9-6.4,1.9-8,0-.1,0-.4-.1-.5-1.1-1.7-17-7.9-20.4-9.3-1.2-.5-7.1-3.4-8.4-3.4h-.5c-1.4,0-2.7-2.1-2.7-3.4s1.2-1.9,2.3-1.9c2.2,0,12.4,5,14.9,6.1,2.6,1.1,5.2,2.2,7.8,3.2,2,.8,6.5,3,8.1,3,1.4,0,1.5-2,3.5-2,1.7,0,1.9,1.3,1.9,2.5v1c0,1.1,1.6,1.9,2.3,2.4,8.5,5.6,22.1,15.6,22.1,26.8,0,9.7-7.3,15-15.6,18.5Zm3.8-30.8c-3.2-3.4-7.5-7.2-11.7-9.4-.6-.3-1.3-.7-2.1-.7-1.1,1-4.5,17.8-5.1,20.4-.4,2.2-1.6,5.5-1.6,7.7,0,.9.4,1.2,1.2,1.2,2,0,19.5-5,22.1-6,.4-.2.9-.4,1.4-.4s1,.3,1,.9c0,3.9-10,6.3-12.8,7.1-2.9.8-23.2,7.6-24.2,8.7-.2.3-.4.6-.4,1,0,.7,1.1.7,1.7.7,2.2,0,4.5-.6,6.7-.9,1.8-.2,3.6-.2,5.4-.4,3.8-.3,7.5-1.2,11.1-2.4,6.4-2,14-8,14-15.3,0-4.6-3.8-9-6.7-12.2Z"/>
~~~ 省略 ~~~
      <path class="cls-1" d="m640.76,64.33l-9.1,5.1c-2.3,1.2-8,5.8-8.5,8.4-.2.9-.2,2.1-.2,3.4-.2,12.6-1,25.5-7.2,31.4-1.6,1.6-4.1,2.9-6.5,2.9-5.1,0-6.5-5.5-6.5-9.7,0-3.1.5-6.2,1.3-9.1,1.2-3.9,2.7-7.6,4.8-11.1l2.8-4.1c1.1-1.5,5.2-6,5.4-7.7.2-1.5.3-3.1.3-4.6v-.4c0-.5,0-1.4-.3-1.4,0,0-7.4,3.9-11.7,3.9-3.6,0-4.6-2.1-4.6-5.4,0-5,4.3-8.9,7.3-12.4,4.2-4.8,10.7-11.1,15.8-15.1,1-.8,2.1-1.3,3.4-1.3,1.5,0,3.3.8,3.3,2.5,0,1.1-1.3,3.1-2.5,3.1,0,0-.2,0-.2.2,0,1.3,2.1,2.1,2.1,5.6,0,1.5-.7,3.1-1,4.5-.9,3.3-2.9,6.2-3.7,9.5-.4,1.8-1.5,3.6-1.5,5.5,0,.2,0,.6.3.6.2,0,6.6-3.6,7.3-3.9.5-.2,11.6-4.9,11.7-4.9.4,0,.6.6.6,1,0,1.6-1.6,2.8-2.9,3.5Zm-23.5,20.3v-.5c0-.2-.1-.3-.2-.3-1.4,0-5.9,8.2-6.5,9.4-.7,1.4-1.3,2.8-1.9,4.3-.7,2.2-1.4,4.5-1.4,6.8,0,1.2.1,6.4,2,6.4,1.6,0,3.8-3.3,4.6-4.4,3-4.5,3.5-11.8,3.5-17,0-1.6-.1-3.2-.1-4.7Zm5.3-37.6c-2.5,0-14.9,14.5-14.9,17.5,0,.9,1.4,1.2,2.1,1.2,2.3,0,5.9-3.4,7.5-4.9,3.4-3.1,5.7-8.3,5.8-12.9,0-.4,0-.9-.5-.9Z"/>
    </g>
  </g>
  <mask id="mask" class="handwriting_mask_line" data-name="レイヤー 2">
    <path id="mask-path" class="handwriting_mask_line" d="m48.29,17.92l-12,50L6.65,8.89s70.26,19.16,65.26,44.16-53.74,18.67-53,18c3.33-3.01,50-19,50.5-19.5l6.45,14.48s27.55-13.48,21.55-21.48c-7.52-10.02-23,23-9,25,13.02,1.86,45-23.12,45-23.12,0,0-.89,28.68-22,18.12-.94-.47-2,7,21,4s31-23,31-23c0,0-13,21-5,26,1.95,1.22,17.09-1.77,22-11,14-43,34-25,34-25,0,0-36,23-28,33,0,0,23-2,21-25-1,4-3.25,6.79-6,28,0,26-4.16,44.93-11,42s-1.93-23.66,11-39c22-12,36-27,36-26s-10,20-7,22c4-2,20-17,21-15,1,3-6,11-1,14s28-9,28-9l22,6s17,1,35-41c7-12-27,40-12,43,30,0,33-28,33-28,0,0-2,15,8,8,2,2-11,16-1,22,11-2,42-14,34-27-15-1-19,24-8,26,18,1,66.59-30.97,46-53-15.41-4.97-27,54-15,60,0,0-5-16,26-38,19,4-20,22-20,22-1,3-1,9,13,10,15-1,63-23,48-54-18-2-23,53-15,60,0-10,22-41,29-38,11,9-19.78,19.55-21.39,21.28-1.61,3.72-1.61,8.72,7.39,9.72,21,5,44-21,41-22s-9,22-4,24c9,2,44-21,41-24-3,0-8,21-7,23,1,0,20-17,21-16,0,2-5,12-1,15,4,2,19-6,19-6,0,0,16-41,33-26,0,0-9.49,5.42-17,13-7,8-11,14-9,17,7,5,27-14,21-23,4,1-1.61,6.78-5,27,0,18,1.93,38.6-11.03,42.3-11.97-2.3,5.03-34.3,8.03-37.3s28-17,28-17l-2-52L158.4,3.55l9,17,141,12h68l150.13-16.03,16.89,7.3"/>
  </mask>
</svg>

整えたソースコード(css)

.block {
  padding: 10%;
}

#text {
  mask: url(#mask);
}

.handwriting {
  width: 100%;
  height: auto;
  &_text {
    fill: #404040;
  }
  &_mask {
    &_line {
      fill: none;
      stroke: #fff;
      stroke-width: 7;
      stroke-linecap: round;
      stroke-linejoin: round;
    }
  }
}

最後に、テキストレイヤーをパスラインでマスクするための#text { mask: url(#mask); }指定して、余計な線が消えていれば下ごしらえ完了です。

おわりに

手書き風テキストアニメーションの準備として、画像作成とスタイル指定の方法を紹介しました。
デザイナーさんが画像作成、エンジニアさんが実装のように、協力して作ることもあるかと思いますので、お互いに作り方を知っているとコミュニケーションもスムーズになりそうですね。

後編では、アニメーションの仕組みと実装方法を紹介します。
お楽しみに♪

後編へつづく…

アバター画像

ぽちっとおうえん!

シェア

  • Facebook
  • LINE
  • X
WPで画像をアップロードしたときにWebpを作成する方法 KNAPのエンジニアが感性を鍛えるために始めたこと