今回はDistortion Hover Effectを使ってカフェメニューを作ってみました。
オンマウスのhover部分のアニメーションにthree.jsを使っています。
Distortion Hover Effectとは
画像にオンマウスした際の画像の切り替えにWebGLを使用したアニメーション効果を使用するものです。
3DCG用ライブラリのthree.jsを使用するのでCSSやjqueryの表現レベルを超えたアニメーションが実現できます。
以下のWebデザインブラッシュアップ解説で作成したデザインを使ってDistortion Hover Effectを実装していきます。
Distortion Hover Effectの実装
以下よりソースをダウンロードします。
WebGL Distortion Hover Effects
imagesloaded.pkgd.min.js(ローディング画面用)、three.min.js、TweenMax.min.js、hover.jsを読み込みます。
※TweenMax.min.jsは用意されていないので以下のようにCDNを使用します。
<script src="js/imagesloaded.pkgd.min.js"></script>
<script src="js/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
<script src="js/hover.js"></script>
HTML
grid__item-img内にドリンクイメージとオンマウス時のイメージを設定します。
data-displacementにはアニメーション画像を設定します。



<div class="grid">
<div class="grid__item">
<div class="grid__item-img" data-displacement="img/displacement/7.jpg" data-intensity="0.9" data-speedIn="0.8" data-speedOut="0.4" data-easing="Circ.easeOut">
<img src="img/drink02.jpg" alt="Image"/>
<img src="img/drink02_h.jpg" alt="Image Alt"/>
</div>
</div>
<div class="grid__item">
<div class="grid__item-img" data-displacement="img/displacement/10.jpg" data-intensity="0.7" data-speedIn="1" data-speedOut="0.5" data-easing="Power2.easeOut">
<img src="img/drink01.jpg" alt="Image"/>
<img src="img/drink01_h.jpg" alt="Image Alt"/>
</div>
</div>
<div class="grid__item">
<div class="grid__item-img" data-displacement="img/displacement/15.jpg" data-intensity="-0.1" data-speedIn="0.4" data-speedOut="0.4" data-easing="power2.easeInOut">
<img src="img/drink03.jpg" alt="Image"/>
<img src="img/drink03_h.jpg" alt="Image Alt"/>
</div>
</div>
</div><!-- grid -->
JS
上記HTMLでのクラス(grid__item-img)を設定します。
<script>
//ローディング
imagesLoaded( document.querySelectorAll('img'), () => {
document.body.classList.remove('loading');
});
//アニメーション
Array.from(document.querySelectorAll('.grid__item-img')).forEach((el) => {
const imgs = Array.from(el.querySelectorAll('img'));
new hoverEffect({
parent: el,
intensity: el.dataset.intensity || undefined,
speedIn: el.dataset.speedin || undefined,
speedOut: el.dataset.speedout || undefined,
easing: el.dataset.easing || undefined,
hover: el.dataset.hover || undefined,
image1: imgs[0].getAttribute('src'),
image2: imgs[1].getAttribute('src'),
displacementImage: el.dataset.displacement
});
});
</script>
css
gridを使用してレイアウトしています。
/* 正方形gridの作り方 */
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding: 5% 5% 0 5%;
}
.grid > *:first-child::after {
content: "";
width: 0px;
padding-bottom: 100%;
grid-row: 1 / 1;
grid-column: 1 / 1;
}
.grid__item {
position: relative;
display: flex;
align-items: stretch;
width: 100vw;
width: 100%;
}
.grid__item-img {
display: block;
height: calc(96% - 5px);
width: calc(96% - 5px);
margin: 2%;
border: 5px solid #FFF94A;
}
/* canvas */
.grid__item-img canvas {
width: 100%!important;
height: 100%!important;
}
.grid__item-img img {
height: 100%;
display: block;
}
/* オンマウス時の画像 */
.grid__item-img img:nth-child(2) {
position: absolute;
top: 0;
left: 0;
opacity: 0;
transition: opacity 0.3s;
}
.grid__item:hover .grid__item-img img:nth-child(2) {
opacity: 1;
}
.js .grid__item-img img {
display: none;
}
サンプルデモ
まとめ
Distortion Hover Effectはcssとjsの作りが汎用的ではないため公式サイトと全く違うデザインに実装するのは敷居が高そうでした。
ただ3Dアニメーションの表現力はWebGLの強みとも言えるので印象付け・差別化・ブランディングなどでは大いに役立ちそうです。

今回カスタマイズするのに結構時間かかっちゃった。。