タグ一覧

Tags

SVGのclipPath要素を使ってモーフィングアニメーションする

もしかしたら中には難しいことをせずに、画像でマスクしてトリミングしている方もいるかもしれませんが、今回は以下の理由があり、SVGのclipPath要素を使うことにしました。

  • デザイナーさんから手書き風に画像をトリミングしたいという要望があった
  • クライアントがCMSから画像を更新するとき、画像を加工する手間を省きたい
  • パスをモーフィングアニメーションさせたい

子猫の顔が全部見えないのが悲しいですが、クリップパスの実装イメージ


実際のコードは以下のURLからご覧ください。

※Part1のソースコードはなんだかぎこちなかったので、改良したソースコードがPart2になります。

実装方法

まずはざっくり大まかな手順をご紹介すると、以下の通りに実装します。

  1. Illustratorのファイルでトリミングしたい形のパスを2種類作る
  2. そのパスの1つをコピペしてclipPath内のpath要素のd属性に挿入する
  3. 2つめのパスは上記と同じpath要素にdata-to属性に挿入する
  4. JSで動かす

Illustratorのファイルでトリミングしたい形のパスを2種類作る

このとき、パスはアニメーション元を複製してアニメーション後のパスを作成したほうが吉です。そして、アンカーの数はアニメーション後も同じ数であることを気をつけて作成してください。

1つめのパスを保存する

Illustrator CCからはパスをコピーすると、テキストエディタにペーストできるようになっています。とても便利です。個人的にはSketchが吐き出すSVGのコードよりもIllustratorのSVGコードのほうが好きなので、Sketchにパスがあった場合にはSVGでエクスポート後、Illustratorで開いて再度SVGとして保存するようにしています。(ただ、ベストはデザイナーさんがパスを用意してくれることだと思います)

2つめのパスを保存する

もし2つめのパスの幅や高さが最初のパスと違った場合、SVGは左上から始まるため、パスの開始位置が変わってしまう場合があります。2つ目のパスを保存するときは、最初のパスの幅と高さに合ったキャンバスを新規作成し、そこに2つめのパスをペーストし、「別名で保存する」するようにしています。

パスの1つをコピペしてまずはクリップパスを実装する

<svg version="1.1" x="0px" y="0px" width="700px" height="290px" viewBox="0 0 700 290">
      <image xmlns:xlink="http://www.w3.org/1001/xlink" xlink:href="http://placekitten.com/700/290" width="700px" height="290px" clip-path="url(#circle)"></image>
      <clipPath id="circle">
      <path class="wave-path" d="M93.4,281.8C237.9,298.2,564.2, ...(省略) "></path>
    </clipPath>
</svg>

svg要素内に、image要素(HTML5では画像を表示する要素はimg要素だけどSVGだとimage要素)を記入し、同じsvg要素内にclipPath要素を記述する。

clipPath要素内には先ほどIllustratorで作成したアニメーション前のパスをpath要素として挿入します。このとき、clipPath要素とimage要素をid属性で紐付けます。

2つめのパスはpath要素にdata-to属性に挿入する

<svg version="1.1" x="0px" y="0px" width="700px" height="290px" viewBox="0 0 700 290">
      <image xmlns:xlink="http://www.w3.org/1001/xlink" xlink:href="http://placekitten.com/700/290" width="700px" height="290px" clip-path="url(#circle)"></image>
      <clipPath id="circle">
      <path class="wave-path" d="M93.4,281.8C237.9,298.2,564.2,...(省略)" data-to="M112.5,261.6c132.5,24.1,415,19.8,463.2,7.4 c46.7-12,85.2-41.3,90.7-63.3c5.5-22,...(省略)"></path>
    </clipPath>
    </svg>

アニメーション前のパスを指定したd属性と同じpath要素内に、アニメーション後のパスを指定するdata-to属性を新しく追加します。なお、この時点ではdata-to属性のパスは表示に影響しません。

Snap.svgでパスを動かす

JSで動かすときは、私の場合path要素にアニメーションを開始したいパスをd属性で指定し、アニメーション後のパスはdata-to属性というオリジナルのdata属性を作成し、挿入します。

今回はSnap.svgというJSのライブラリを使い、d属性とdata-to属性で指定したパスの値をループしてアニメーションできるようにしました。

var snaps = Snap.selectAll('.wave-path');

// それぞれの.wave-pathに対してアニメーションを実行する
[].forEach.call(snaps,function(snap){
  var pathFrom = snap.attr('d');
  var pathTo = snap.attr('data-to');
  
  function infAnim( el ,dir) {
    var start,end;
    if(dir ==='up'){
      start = pathFrom;
      end = pathTo;
      dir = 'down';
    }else{
	    start = pathTo;
      end = pathFrom;
      dir = 'up';
    }
    el.attr('d', start);
        el.animate({d:end},3000,mina.linear,function(){
        infAnim(el,dir);
      });
    }
  infAnim(snap,'up');
})

実装途中につまずいた点

SVGは使うたびにどこかでつまずいてしまうので、今回使った点で苦労した点を以下にまとめます。

  • はじめCSSのclip-pathプロパティで実装しようとしてつまずいた
  • 画像がclipPathで指定したパスにそわずに途切れてしまう
  • 用意されたパスでうまくアニメーションしなかった

はじめCSSのclip-pathプロパティで実装しようとしてつまずいた

クリップパスを実装する方法としては、私が今回採用したSVGのclipPath要素を使う方法と、CSSからトリミングしたいクリップパスのid属性を指定する方法があります。はじめ、CSSでトリミングする方法を採用しようとしたのですが、なかなか扱いが難しく、ブラウザ対応もまだまだということもあり、断念しました。株式会社まぼろしの松田さんにSVGのclipPath要素を使う方法を教えていただき、実装することができました。個人的にはclipPath要素で指定する方がトラブルが少なく実装できました。

画像がclipPathで指定したパスにそわずに途切れてしまう

試行錯誤していたら、画像のザイズやSVGの大きさが切り抜きたいサイズに合っていなかったことが原因でした。widthを100%にしたらなんとかいい感じに収縮してくれるだろうという甘い考えがあったのですが、そんなことはありませんでした。サイズはきっちり指定しましょう。

用意されたパスでうまくアニメーションしなかった

デザイナーさんにIllustratorでアニメーションするためのパスを2種類用意していただいたのですが、なぜかパスが指定した形ではなく、SVGの中心へと縮む現象が起きてしまいました。コードを見てみると、新しくパスを作られたようで、アニメーション元のパスを複製してアニメーション後のパスを作ると正常にアニメーションされました。

アニメーション元のパスからアニメーション後のパスを作ったほうが無難なようです。

最後に

実はSnap.svgではなくGreenSockを使ってみよう!と思ったのですが、JSのスキルが無い私にはサンプルコードがまだ少ないGreenSockはハードルが高かったので、断念しました。力不足でとても悔しいので、もうすこし私のJSスキルの上昇、またはGreenSock関連の記事が増えてきたら再度トライしたい...!

以下、参考になった記事のご紹介です。

あとは、ちょうどセミナーに講師としてお呼びしていたまぼろしの松田さんに直接クリップパスについてお伺いしたり、JavaScriptの面ではアップルップル堀さんにもご協力いただきました。私の知識だけでは実装できなかったので、とても助かりました。ありがとうございました!


この記事をシェアする

著者

デザイナー

森田かすみ

名古屋のスタートアップで働く、デジタルプロダクトデザイナー。

2013年に新卒でWeb制作会社に入社し、受託制作のマークアップエンジニアとして勤務した後、CMS開発部門のデザイナーへ転身。

2023年5月にSaaSのプロダクトデザイナーへ転身。
現在は新機能にまつわるUXを考慮したUI設計、機能マーケティング支援などを担当。
ストレス発散方法はかっぱのイラストを描くこと。

おすすめ記事

この記事のハッシュタグ から関連する記事を表示しています。

他の方法で記事を探す

2024年4月

年間カレンダーへ
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30