「モーフィングアニメーション」は、「ある形」から「ある形」へシームレスに変化するアニメーションのことですが、「HTML」と「CSS」で作成する方法をご紹介したいと思います。
「モーフィングアニメーション」の仕組み
「モーフィングアニメーション」は「パス」と呼ばれる情報を定義し、その「パスの位置」を移動させることで実現します。
「illustrator」をお使いの方は「illustrator」の「パス」や「クリッピングマスク」とよく似た機能になります。
CSSの「clip-path」プロパティ
「WEBサイト製作」では、「CSS」の「clip-path」プロパティを使うことで、「要素の表示範囲」を指定することができます。
「clip-pathの指定方法」にはさまざまなものがあります。
circle
「円」の形で表示領域を限定することができます。
例えば
のような長方形の画像に、
clip-path: circle(30%);
を適用すると、
のように表示されます。
「円の位置」を指定することもできます。
clip-path: circle(30% at 0px 0px);
と指定すると、
のように表示されます。
「円の中心」が「画像の左上」に配置され、ここが原点となります。
clip-path: circle(30% at 20px 50px);
と設定すると、
「at」の右横の「20px」の値を増やすと右に移動し、「50px」の値を増やすと下に移動します。
ellipse
「ellipse」は「楕円」で表示範囲を指定することができます。
のような画像に
clip-path: ellipse(80px 50px);
と指定すると、
のように表示されます。
「ellipse」で指定をしている「120px」は横方向の大きさで「80px」は縦方向の大きさになります。
「楕円」の位置を指定することもでき、「円」と同様に「画像の左上」が原点となります。
clip-path: ellipse(120px 80px at 20px 30px);
と指定をすると、「楕円の表示範囲」が「画像の左上」から「右方向へ20px」移動し、「下方向へ30px」移動します。
path
「SVG」のパス指定を用いて表示範囲を指定することができます。
例えば、
のような画像に、
clip-path: path("M0,0 L100,200 L50,300 Z");
を指定すると、
のように表示されます。
今回の「モーフィングアニメーション」では利用しない方法のため、詳しい指定方法は「SVGパスの定義方法」について調べてみてください。
polygon
「多角形」を指定して、表示範囲を指定することができます。
例えば、
のような画像に、
clip-path:polygon(0% 0%, 100% 10%, 91% 100%, 1% 82%);
を指定すると、
のように表示されます。
「モーフィングアニメーション」ではこの方法を利用していくため、詳しく見ていきたいと思います。
先ほどの設定は下図のようになっています。
画像の左上が「0%」で横方向の右端が「100%」。
そして、縦方向の下端が「100%」となっています。
clip-path:polygon(横方向1 縦方向1, 横方向2 縦方向2, ・・・);
のように表示範囲を囲むポイントを指定していきます。
「モーフィングアニメーション」の作り方
「モーフィングアニメーション」を作成するためには「2つのpolygon」が必要になります。
「polygon」の作り方
「変形前のpolygon」と「変更後のpolygon」を作成する必要がありますが、大切なことは「polygonのデータ数」を合わせることです。
例えば、「変形前のpolygon」の「データ数」が「4」であれば、「変更後のpolygon」も「データ数」を「4」にする必要があります。
今回は下のような写真を利用して「モーフィングアニメーション」を作っていきたいと思います。
ワッフルの部分を表示範囲に設定してみたいと思います。
では、どのように「polygon」の設定値を求めるのかですが、あらかじめ、「0%~100%」の「横と縦の格子状のシート」を用意しておく方法があります。
この「格子状のシート画像」を「表示したい画像」と重ね合わせます。
表示を限定したい範囲の「ポイントの値」を取得します。
ワッフルを表示範囲にしたいため「ワッフル」の4隅のポイントを調べます。
clip-path:polygon(38% 38%, 59% 53%, 45% 82%, 25% 66%);
この値を適用してみると、
のように表示されます。
この状態を「アニメーション前の状態」とします。
次に「アニメーション後の状態」を定義したいと思いますが、「アニメーション後」は「画像全体」を表示したいので、「画像の4隅のポイント」を取得します。
このポイントの「clip-path」は、
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
のようになります。
「アニメーション」の作成
「ワッフル」の画像にマウスが重なった時にアニメーションをしたいと思います。
パソコンをお使いの方は、下のワッフル画像にマウスカーソルを合わせてみてください。
「ワッフルの背景画像」が表示されると思います。
この画像の「HTMLコード(img要素)」は、
<img src="https://www.webdesign-ls.com/wp-content/uploads/2023/11/morph_anim_002.jpg" class="morph_img_001">
のようになっています。
CSSは、
.morph_img_001 {
/* マウスカーソルを重ねる前 */
clip-path: polygon(38% 38%, 59% 53%, 45% 82%, 25% 66%);
transition: all 1s ease;
}
.morph_img_001:hover {
/* マウスカーソルを重ねた後 */
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
}
のようになります。
「マウスオーバー(ホバー)」では無く、「クリック」など他のタイミングでアニメーションしたい場合は「Javascript」などを利用すると実現することができます。
今回は4点でしたが「polygon」の「頂点(ポイント)」数は増やすことができます。
「clip-path」の値を「アニメーション前後」で入れ替えると、「マウスオーバー」することで、画像の表示範囲を限定することもできます。
例えば、
.morph_img_002 {
/* マウスカーソルを重ねる前 */
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
transition: all 1s ease;
}
.morph_img_002:hover {
/* マウスカーソルを重ねた後 */
clip-path: polygon(38% 38%, 59% 53%, 45% 82%, 25% 66%);
}
のように作成すると、
「マウスカーソル」を画像に重ねることで、表示範囲がが限定されます。
「polygon」が多数の「モーフィングアニメーション」
「人物」のような複雑な写真なども同様に表示することができます。
例えば、
のような写真の人物の表示範囲を限定するためには、
clip-path:polygon(44% 38%, 45% 36%, 47% 34%, 49% 33%, 52% 33%, 55% 35%, 58% 39%, 59% 41%, 59% 43%, 61% 45%, 64% 45%, 66% 48%, 67% 51%, 67% 55%, 66% 59%, 65% 62%, 65% 65%, 66% 75%, 68% 86%, 68% 87%, 67% 88%, 58% 93%, 61% 100%, 52% 100%, 49% 96%, 48% 92%, 46% 89%, 45% 92%, 44% 96%, 44% 100%, 36% 100%, 35% 95%, 35% 91%, 35% 85%, 35% 79%, 36% 74%, 38% 70%, 38% 68%, 38% 62%, 39% 57%, 41% 54%, 43% 51%, 42% 48%, 41% 46%, 41% 43%, 42% 40%);
のような多数のポイント指定が必要になります。
このポイントを元に写真を表示すると、
のようになります。
「モーフィングアニメーション」を作りましたので、PCの方は下の写真にマウスを重ねてみてください。
「複雑な形」でも「モーフィングアニメーション」ができますが、「アニメーション前後」の「ポイント数」を合わせないとうまくアニメーションしてくれません。
「Javascript」を利用した「モーフィングアニメーション」
「Javascript」を利用すると「任意のタイミング」でアニメーションを行うことができます。
2STEPのモーフィングアニメーション
例えば、ある要素が「画面内に表示された時」や「クリックされた時」など、さまざまなタイミングで「アニメーションの表示」を行うことが可能です。
このまま下にスクロールしてみてください。
画像が画面に表示されるタイミングでアニメーションが実行されます。
アニメーションが実行されない場合は再読み込みをしてみてください。
これまでは、「transition」を利用したシンプルなアニメーションでしたが、今回は「animationプロパティ」を利用した「2STEPのアニメーション」となっています。
HTMLは、
<img src="https://www.webdesign-ls.com/wp-content/uploads/2023/11/006.jpg" class="morph_img_004">
のように「画像の要素」を作成し、CSSは、
.morph_img_004 {
clip-path: polygon(49% 49%, 50% 49%, 50% 50%, 49% 50%);
opacity: 0;
}
.morph_img_004.active {
animation: clip-path-anim 1s ease-in-out 0s forwards;
}
@keyframes clip-path-anim {
0% {
opacity: 1;
clip-path: polygon(49% 49%, 50% 49%, 50% 50%, 49% 50%);
}
/* 横方向いっぱいまで広がる */
30% {
clip-path: polygon(0% 49%, 100% 49%, 100% 50%, 0% 50%);
}
/* 画像の大きさいっぱいまで広がる */
100% {
opacity: 1;
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0 100%);
}
}
のようになっています。
アニメーションの「@keyframes」を見ると、「0%~30%」までは横方向いっぱいに広がるアニメーションで、「30%~100%」までは画像の大きさいっぱいまで広がるアニメーションになっています。
「Javascript(jQuery)」は、
$(document).ready(function(){
$(window).scroll(function(){
/* 「画面の下端」が「画像の位置」より下になった時 */
if($('.morph_img_004').offset().top < $(window).scrollTop() + $(window).height()){
if( !$('.morph_img_004').hasClass('active') ){
/* 画像に「activeクラス」を追加してアニメーションをスタート */
$('.morph_img_004').addClass('active');
}
}
});
});
のようになっています。
画像が画面内に来たタイミングで画像に「active」というクラスを追加してアニメーションを実行しています。
アイディアしだいでさまざまな「アニメーションパターン」を作ることができます。
さらにスクロールしてみてください。
このアニメーションのHTMLは、
<img src="https://www.webdesign-ls.com/wp-content/uploads/2023/11/006.jpg" class="morph_img_005">
のように作成し、
.morph_img_005 {
clip-path: polygon(49% 49%, 50% 49%, 50% 50%, 49% 50%);
opacity: 0;
}
.morph_img_005.active {
animation: clip-path-anim02 1s ease-in-out 0s forwards;
}
@keyframes clip-path-anim02 {
0% {
opacity: 1;
clip-path: polygon(49% 49%, 50% 49%, 50% 50%, 49% 50%);
}
30% {
clip-path: polygon(0% 0%, 50% 49%, 100% 100%, 49% 50%);
}
100% {
opacity: 1;
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0 100%);
}
}
のようになっています。
複数STEPのモーフィングアニメーション
2STEPだとシンプルなモーフィングアニメーションしか作れませんが、複数STEPのモーフィングアニメーションは多彩な表現を行うことができます。
このままスクロールしてみてください。
Javascriptはこれまでと変わりませんが、CSSの設定量が増えています。
.morph_img_006 {
width: 1000px;
height: 667px;
clip-path: polygon(46% 32%, 48% 30%, 51% 28%, 53% 28%, 55% 28%, 58% 29%, 60% 31%, 61% 34%, 62% 37%, 63% 40%, 63% 43%, 62% 49%, 60% 53%, 58% 55%, 57% 56%, 53% 57%, 49% 56%, 46% 54%, 44% 50%, 43% 47%, 42% 42%, 43% 37%, 44% 34%);
opacity: 1;
}
.morph_img_006.active {
animation: clip-path-anim03 5s ease-in-out 0s forwards;
}
@keyframes clip-path-anim03 {
0% {
opacity: 1;
clip-path: polygon(46% 32%, 48% 30%, 51% 28%, 53% 28%, 55% 28%, 58% 29%, 60% 31%, 62% 34%, 63% 37%, 64% 40%, 64% 43%, 63% 49%, 61% 53%, 59% 55%, 57% 57%, 53% 58%, 49% 56%, 46% 54%, 44% 50%, 43% 47%, 42% 42%, 43% 37%, 44% 34%);
}
10% {
clip-path: polygon(59% 65.5%, 61% 67.5%, 63% 68.5%, 65% 70%, 68% 73%, 70% 75%, 72% 76%, 70% 82%, 68.5% 86%, 67% 90%, 66% 94%, 65% 97%, 62% 95%, 59% 92%, 57% 90%, 54% 88%, 51% 86%, 52% 84%, 54% 80%, 55% 76%, 56% 73%, 57% 70%, 58% 67%);
}
20% {
clip-path: polygon(59% 65.5%, 61% 67.5%, 63% 68.5%, 65% 70%, 68% 73%, 70% 75%, 72% 76%, 70% 82%, 68.5% 86%, 67% 90%, 66% 94%, 65% 97%, 62% 95%, 59% 92%, 57% 90%, 54% 88%, 51% 86%, 52% 84%, 54% 80%, 55% 76%, 56% 73%, 57% 70%, 58% 67%);
}
30% {
clip-path: polygon(26.5% 72%, 27.5% 69%, 29% 67%, 31% 65%, 34.5% 63%, 38% 63%, 41% 64%, 43% 66%, 45% 69%, 46.5% 72%, 47% 76%, 47% 79%, 46.2% 85%, 45% 89%, 43% 92%, 40% 94%, 36% 96%, 33% 96%, 30% 94%, 27.2% 90%, 26% 86%, 25% 82%, 25% 79%);
}
40% {
clip-path: polygon(26.5% 72%, 27.5% 69%, 29% 67%, 31% 65%, 34.5% 63%, 38% 63%, 41% 64%, 43% 66%, 45% 69%, 46.5% 72%, 47% 76%, 47% 79%, 46.2% 85%, 45% 89%, 43% 92%, 40% 94%, 36% 96%, 33% 96%, 30% 94%, 27.2% 90%, 26% 86%, 25% 82%, 25% 79%);
}
50% {
clip-path: polygon(75% 40%, 78% 38%, 81% 38%, 83% 38%, 86% 40%, 89% 44%, 91% 48%, 91.5% 53%, 91.5% 57%, 90% 61%, 88.5% 64.5%, 87% 65.8%, 85% 67.2%, 82% 68.2%, 79% 68%, 76% 66%, 74% 64%, 73% 62%, 72% 59%, 71% 56%, 71% 53%, 71% 49%, 72% 45%);
}
60% {
clip-path: polygon(75% 40%, 78% 38%, 81% 38%, 83% 38%, 86% 40%, 89% 44%, 91% 48%, 91.5% 53%, 91.5% 57%, 90% 61%, 88.5% 64.5%, 87% 65.8%, 85% 67.2%, 82% 68.2%, 79% 68%, 76% 66%, 74% 64%, 73% 62%, 72% 59%, 71% 56%, 71% 53%, 71% 49%, 72% 45%);
}
70% {
clip-path: polygon(21% 31%, 23% 29%, 26% 27%, 29% 26%, 31% 27%, 34% 29%, 36% 31%, 37% 33%, 38% 36%, 38% 42%, 37% 47%, 35% 50%, 32% 53%, 29% 55%, 26% 55%, 23% 54%, 21% 53%, 20% 51%, 19% 48%, 18% 45%, 18% 41%, 19% 36%, 20% 33%);
}
80% {
opacity: 1;
clip-path: polygon(21% 31%, 23% 29%, 26% 27%, 29% 26%, 31% 27%, 34% 29%, 36% 31%, 37% 33%, 38% 36%, 38% 42%, 37% 47%, 35% 50%, 32% 53%, 29% 55%, 26% 55%, 23% 54%, 21% 53%, 20% 51%, 19% 48%, 18% 45%, 18% 41%, 19% 36%, 20% 33%);
}
90% {
opacity: 0;
clip-path: polygon(47% 47%, 47% 46%, 47% 45%, 47% 44%, 47% 43%, 47% 42%, 47% 41%, 47% 40%, 47% 39%, 47% 38%, 48% 38%, 49% 38%, 50% 38%, 51% 38%, 52% 38%, 53% 38%, 54% 38%, 55% 38%, 56% 38%, 57% 38%, 53% 41%, 52% 43%, 50% 45%);
}
100% {
opacity: 1;
clip-path: polygon(1% 1%, 18% 1%, 39% 1%, 66% 1%, 85% 1%, 100% 1%, 100% 15%, 100% 37%, 100% 59%, 100% 79%, 100% 100%, 89% 100%, 74% 100%, 57% 100%, 46% 100%, 33% 100%, 18% 100%, 1% 100%, 1% 86%, 1% 71%, 1% 53%, 1% 39%, 1% 20%);
}
}
作成する「clip-path」のデータ量も増えるため作成に時間がかかりますが、「モーフィングアニメーション」は見た目のインパクトもあるため、「注目してほしいポイント」に効果的に使うと良いのではないでしょうか。
ぜひご自身の「オリジナルモーフィングアニメーション」の作成にチャレンジしてみていただければと思います。