メモ:文字を手書きで書いているような演出をSVGとVivus.jsで実装する

英語の筆記体をサラサラっと書くようなアニメーション演出って可能なんだろうか。そんな疑問からGoogleを調べてみたら、目的に近い方法を見つけることが出来ました。

この記事では、実際に試してみた際の流れと、作業の中で気づいた要点をメモしてみます。

参考にした記事

SVGで手書き風アニメーションを実装する方法 | Will Style Inc.|神戸にあるウェブ制作会社

動かすとこんな見た目になります

手順1:手書きで表現したい文字をアウトライン化してSVGで書き出す

Adobe IllustratorやAdobe XDなど、入力したテキストをアウトライン化できるアプリで、手書きで表現したい文字を打つ

※書き出されるSVGのソースコードが少しきれいになるので、アートボードは0,0をベースに、横と縦のサイズは整数に設定しておこう。

これをアウトライン化して、SVGで書き出す

手順2:SVG内の文字をなぞるマスク用パスを作りSVGで書き出しておく

上記のように、文字のレイヤーの上に新たに「mask」というレイヤーを作成。一筆書きの要領で、最初の文字から最後の文字までパスでなぞっていきます。実際の手書き演出も、なぞった順に文字が表示されます。
なぞったパスに色をつけたものです。パスの太さは、下のレイヤーの文字をしっかり隠せる程度に太く設定しておくと○です。
SVGを書き出す時は、レイヤーをマスクのパスがあるレイヤーだけにしておきます。この後、手順1同様に、SVGファイルを書き出します(ファイル名は何でもOKですが、ここでは「mask.svg」とします。

パスの複雑さにもよりますが、書き出されたmask.svgのソースコードは、下記のような感じの見た目になるはずです。<pathから始まる箇所で、手書きの軌道を定義しています。

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="mask" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 600 150" style="enable-background:new 0 0 600 150;" xml:space="preserve">
<style type="text/css">
	.st0{fill:none;stroke:#FFFFFF;stroke-width:5.4631;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
</style>
<path class="st0" d="M24,105.7c0,0-9.9-50.1,0.4-80.6c0,0,45.7,9.4,43.5,38.5s-34.6,42-34.6,42l-17.8,5.8l6.3,4.6l31.9-10.3L70.4,74
	V56.4v-4.3l7.3-0.7l0.5,9.7v14l-0.5,10.2l-1.1,11.8c0,0-0.2,8.7,5.5,10.1c5.6,1.3,12.5-8.4,12.5-8.4s12.1-18.4,13.7-27.8
	c1.6-9.3,0-6.8,0-6.8l0.7,21.2c0,0,0.2,14.1,6.3,19.4c6.1,5.2-1.4-16.2-1.4-16.2l6.3-27.3l1.7-4.6l6.6-3v3.4c0,0-8,23.7-5.7,47.3
	l-0.2,3.8l1.4-2.5c0,0,9.1-41.1,17.8-40.2C150.3,66.4,150,76,150,76s5.8,24.6,4.8,31.2c0,0,16.3-44.6,25-44.8
	c6.1,0.2,7.8,46.7,7.8,46.7l-2.8,1l-5.9-28.1l10.7-31l14.4,3.4V56c0,0-11.2,33.5-5.7,49.8l0.5,2.6c0,0,8.2-43.2,17.8-43.7
	c9.6-0.5,13.1,43.9,13.1,43.9s14.7-44.8,25.1-46.4c0,0,6.6,8.7,7.5,43.6l0.4,3.5L254.3,74l10.1-17.1l4.3,1.6c0,0,5.9,0.5,5.9,6.1
	s-1.4,27.5-1.4,27.5s0.4,4,2.5,4.8c2.1,0.7,27.1-34.8,27.1-34.8l1.1,37.1c0,0,3.2,14.3,1.6,18.9s-17,34.1-44.6,15.2l-3.4-4.5
	l-2,10.8l98.8-70l10-3.3l11.3-2.9l9-1.8l8.9,0.1l3.5-13.4l-5.2-4.7l-5.7,6.6l-11.6-10.5c0,0-7.7,42.3-0.5,65.2
	c0,0,18.5,14.6,36.7-19.4l-9.8,4l3.9,10.9h2.5c0,0,22.3-6.3,37.8-26.4c0,0,0.7-8.7-9.8-11.6S421.8,76,421.8,76s-3.6,14.1,0.2,24.3
	s14.3,8.2,14.3,8.2s11.4-2.8,19.1-17.9c7.7-15.1-5.7-36.5-5.7-36.5l11.8,0.7c0,0,7.3,25.9,13,34.4c5.7,8.4,14.3,17.8,16.4,18.7
	c2,0.9,4.6,0,4.6,0l3.8-1.8l0.5-5.7l-7.3-22.7l0.5-6l0.9-6.4c0,0-18.3,8.2-25.3,23.7s-3.6,24.6-3.6,24.6l30.3,2l-9.1-32.7v-5.3
	l9.6-7.3l28.7-8l18-0.7l-11.8-13.4l-9.8-8.4c0,0-3.9,34-3.4,41.3c0.5,7.4-1,27.8,11.3,26.9s15.1-5,15.1-5s12.8-11.4,13.7-20.2
	c0.9-8.7,1.1-11.5,1.1-11.5l1.8-42.9l17.1-16.2l1.1,7.6c0,0-5.2,18.8-4.7,33.1s0.6,16.8,0.6,16.8l1.8,15l-0.7,7.5l-1.4,3.9l1.4,4.9
	l1.8,3.8l2,2.5l1.5,2.3l3.1,3l3,2.1"/>
</svg>

手順3:HTML内に、実装に必要な記述を行う

ここからは、組み込むコードごとに順番に記述していきます。

mask.svg内の<style>の記述をHTMLの<head>内にペースト

<style type="text/css">
	.st0{fill:none;stroke:#FFFFFF;stroke-width:5.4631;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
</style>
</head>

SVGとマスクをコピペする枠を<body>内に作る

<div class="svgdiv">
<svg>
<mask id="clipmask" maskUnits="objectBoundingBox">
</mask>  
</svg>
</div>
  • 大枠のdivは、無くても問題ありません。後でCSSを適用するために囲っておきました。
  • 大枠のdivのclass名は”svgdiv”としてありますが、お好みでOKです。

mask.svgを開き、<svg>の部分をコピーし下記のようにペースト

<div class="svgdiv">
<svg version="1.1" id="mask" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 600 150" style="enable-background:new 0 0 600 150;" xml:space="preserve">
<mask id="clipmask" maskUnits="objectBoundingBox">
</mask>  
</svg>
</div>

描画したいSVGファイルを読み込む

<div class="svgdiv">
<svg version="1.1" id="mask" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 600 150" style="enable-background:new 0 0 600 150;" xml:space="preserve">
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="dummy.svg" width="600" height="150" mask="url(#clipmask)"></image>
<mask id="clipmask" maskUnits="objectBoundingBox">
</mask>  
</svg>
</div>
  • 上記では、SVGのファイル名は「dummy.svg」としてあります。
  • widthとheightは、SVGを書き出したアートボードのサイズを記載しておきます。

mask.svg内の、<path>の部分を<mask>内にペースト

<div class="svgdiv">
<svg version="1.1" id="mask" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 600 150" style="enable-background:new 0 0 600 150;" xml:space="preserve">
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="dummy.svg" width="600" height="150" mask="url(#clipmask)"></image>
<mask id="clipmask" maskUnits="objectBoundingBox">
<path class="st0" d="M24,105.7c0,0-9.9-50.1,0.4-80.6c0,0,45.7,9.4,43.5,38.5s-34.6,42-34.6,42l-17.8,5.8l6.3,4.6l31.9-10.3L70.4,74
	V56.4v-4.3l7.3-0.7l0.5,9.7v14l-0.5,10.2l-1.1,11.8c0,0-0.2,8.7,5.5,10.1c5.6,1.3,12.5-8.4,12.5-8.4s12.1-18.4,13.7-27.8
	c1.6-9.3,0-6.8,0-6.8l0.7,21.2c0,0,0.2,14.1,6.3,19.4c6.1,5.2-1.4-16.2-1.4-16.2l6.3-27.3l1.7-4.6l6.6-3v3.4c0,0-8,23.7-5.7,47.3
	l-0.2,3.8l1.4-2.5c0,0,9.1-41.1,17.8-40.2C150.3,66.4,150,76,150,76s5.8,24.6,4.8,31.2c0,0,16.3-44.6,25-44.8
	c6.1,0.2,7.8,46.7,7.8,46.7l-2.8,1l-5.9-28.1l10.7-31l14.4,3.4V56c0,0-11.2,33.5-5.7,49.8l0.5,2.6c0,0,8.2-43.2,17.8-43.7
	c9.6-0.5,13.1,43.9,13.1,43.9s14.7-44.8,25.1-46.4c0,0,6.6,8.7,7.5,43.6l0.4,3.5L254.3,74l10.1-17.1l4.3,1.6c0,0,5.9,0.5,5.9,6.1
	s-1.4,27.5-1.4,27.5s0.4,4,2.5,4.8c2.1,0.7,27.1-34.8,27.1-34.8l1.1,37.1c0,0,3.2,14.3,1.6,18.9s-17,34.1-44.6,15.2l-3.4-4.5
	l-2,10.8l98.8-70l10-3.3l11.3-2.9l9-1.8l8.9,0.1l3.5-13.4l-5.2-4.7l-5.7,6.6l-11.6-10.5c0,0-7.7,42.3-0.5,65.2
	c0,0,18.5,14.6,36.7-19.4l-9.8,4l3.9,10.9h2.5c0,0,22.3-6.3,37.8-26.4c0,0,0.7-8.7-9.8-11.6S421.8,76,421.8,76s-3.6,14.1,0.2,24.3
	s14.3,8.2,14.3,8.2s11.4-2.8,19.1-17.9c7.7-15.1-5.7-36.5-5.7-36.5l11.8,0.7c0,0,7.3,25.9,13,34.4c5.7,8.4,14.3,17.8,16.4,18.7
	c2,0.9,4.6,0,4.6,0l3.8-1.8l0.5-5.7l-7.3-22.7l0.5-6l0.9-6.4c0,0-18.3,8.2-25.3,23.7s-3.6,24.6-3.6,24.6l30.3,2l-9.1-32.7v-5.3
	l9.6-7.3l28.7-8l18-0.7l-11.8-13.4l-9.8-8.4c0,0-3.9,34-3.4,41.3c0.5,7.4-1,27.8,11.3,26.9s15.1-5,15.1-5s12.8-11.4,13.7-20.2
	c0.9-8.7,1.1-11.5,1.1-11.5l1.8-42.9l17.1-16.2l1.1,7.6c0,0-5.2,18.8-4.7,33.1s0.6,16.8,0.6,16.8l1.8,15l-0.7,7.5l-1.4,3.9l1.4,4.9
	l1.8,3.8l2,2.5l1.5,2.3l3.1,3l3,2.1"/>
</mask>  
</svg>
</div>

手書き表現が出来るJavaScript「Vivus.js」を<body>直前付近に読み込む

<div class="svgdiv">
<svg version="1.1" id="mask" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 600 150" style="enable-background:new 0 0 600 150;" xml:space="preserve">
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="dummy.svg" width="600" height="150" mask="url(#clipmask)"></image>
<mask id="clipmask" maskUnits="objectBoundingBox">
<path class="st0" d="M24,105.7c0,0-9.9-50.1,0.4-80.6c0,0,45.7,9.4,43.5,38.5s-34.6,42-34.6,42l-17.8,5.8l6.3,4.6l31.9-10.3L70.4,74
	V56.4v-4.3l7.3-0.7l0.5,9.7v14l-0.5,10.2l-1.1,11.8c0,0-0.2,8.7,5.5,10.1c5.6,1.3,12.5-8.4,12.5-8.4s12.1-18.4,13.7-27.8
	c1.6-9.3,0-6.8,0-6.8l0.7,21.2c0,0,0.2,14.1,6.3,19.4c6.1,5.2-1.4-16.2-1.4-16.2l6.3-27.3l1.7-4.6l6.6-3v3.4c0,0-8,23.7-5.7,47.3
	l-0.2,3.8l1.4-2.5c0,0,9.1-41.1,17.8-40.2C150.3,66.4,150,76,150,76s5.8,24.6,4.8,31.2c0,0,16.3-44.6,25-44.8
	c6.1,0.2,7.8,46.7,7.8,46.7l-2.8,1l-5.9-28.1l10.7-31l14.4,3.4V56c0,0-11.2,33.5-5.7,49.8l0.5,2.6c0,0,8.2-43.2,17.8-43.7
	c9.6-0.5,13.1,43.9,13.1,43.9s14.7-44.8,25.1-46.4c0,0,6.6,8.7,7.5,43.6l0.4,3.5L254.3,74l10.1-17.1l4.3,1.6c0,0,5.9,0.5,5.9,6.1
	s-1.4,27.5-1.4,27.5s0.4,4,2.5,4.8c2.1,0.7,27.1-34.8,27.1-34.8l1.1,37.1c0,0,3.2,14.3,1.6,18.9s-17,34.1-44.6,15.2l-3.4-4.5
	l-2,10.8l98.8-70l10-3.3l11.3-2.9l9-1.8l8.9,0.1l3.5-13.4l-5.2-4.7l-5.7,6.6l-11.6-10.5c0,0-7.7,42.3-0.5,65.2
	c0,0,18.5,14.6,36.7-19.4l-9.8,4l3.9,10.9h2.5c0,0,22.3-6.3,37.8-26.4c0,0,0.7-8.7-9.8-11.6S421.8,76,421.8,76s-3.6,14.1,0.2,24.3
	s14.3,8.2,14.3,8.2s11.4-2.8,19.1-17.9c7.7-15.1-5.7-36.5-5.7-36.5l11.8,0.7c0,0,7.3,25.9,13,34.4c5.7,8.4,14.3,17.8,16.4,18.7
	c2,0.9,4.6,0,4.6,0l3.8-1.8l0.5-5.7l-7.3-22.7l0.5-6l0.9-6.4c0,0-18.3,8.2-25.3,23.7s-3.6,24.6-3.6,24.6l30.3,2l-9.1-32.7v-5.3
	l9.6-7.3l28.7-8l18-0.7l-11.8-13.4l-9.8-8.4c0,0-3.9,34-3.4,41.3c0.5,7.4-1,27.8,11.3,26.9s15.1-5,15.1-5s12.8-11.4,13.7-20.2
	c0.9-8.7,1.1-11.5,1.1-11.5l1.8-42.9l17.1-16.2l1.1,7.6c0,0-5.2,18.8-4.7,33.1s0.6,16.8,0.6,16.8l1.8,15l-0.7,7.5l-1.4,3.9l1.4,4.9
	l1.8,3.8l2,2.5l1.5,2.3l3.1,3l3,2.1"/>
</mask>  
</svg>
</div>

<script src="https://cdn.jsdelivr.net/npm/vivus@latest/dist/vivus.min.js"></script>
<script>
new Vivus('mask', {type: 'scenario-sync',duration: 100,forceRender: false ,animTimingFunction:Vivus.EASE})
</script>
</body>
  • <script>内の new Vivus(‘mask’〜の”mask”は、<svg>タグのidと連動しているので、もしsvgのidを変更する時は、こちらの”mask”も、変更した名前に合わせよう。
  • Vivus.jsでは、出現の仕方、スピードなど、いろいろなパラメータが設定できる。詳しくはドキュメントをチェックしよう(ただし英語)。

実際に出来たもの

デモを見る

ここまでお読みいただき、ありがとうございました。自分用のメモなので分かりにくい記述ではありますが、お役に立てれば幸いです。

0