実装の考え方
マウスの位置に応じてカードを傾けるには、マウスの位置をJavaScriptで取得し、その位置に応じて計算して傾けるようにします。傾きに関しては、CSSのtransform: rotateX() rotateY()を使用します。
実装方法
それでは実際に実装していきましょう。
まずはHTMLになります。
HTML
<div class="card-hover-range">
<div class="card">
<div class="card__img">
<img src="https://picsum.photos/320/180?random=1" alt="" width="320" height="180">
</div>
<div class="card__text">
<h2 class="card__title">Card Tilt</h2>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Rerum consequatur aliquid quo vel dolor, possimus asperiores optio quas expedita rem inventore cum voluptatibus sed, labore enim, a quidem iste aspernatur.</p>
</div>
</div>
</div>
傾くカードはcardクラスになります。card-hover-rangeはカードが傾くマウスの範囲を広げるために、親要素として使用します。
CSS
CSSは次の通りになります。
.card-hover-range {
padding: 5rem;
}
.card {
width: 400px;
background-color: #fff;
border-radius: 1rem;
border: 1px solid #000;
transition: transform 0.3s linear;
}
card-hover-rangeはカードが傾くマウスの範囲を広げるために、paddingで広げます。cardがtransformで傾くので、transitionを設定しておきます。デフォルトではイージングがeaseなので、linearに変更し、直ぐに傾くようにします。
JavaScript
最後にJavaScriptになります。
const cardMouseRange = document.querySelector(".card-hover-range");
const card = document.querySelector(".card");
const MaxRotate = 30;
cardMouseRange.addEventListener('mousemove', (e) => {
const rect = card.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = (e.clientY - rect.top) / rect.height;
const rotateX = (0.5 - y) * MaxRotate;
const rotateY = (0.5 - x) * MaxRotate;
card.style.transform = `rotateX(${rotateX}deg) rotateY(${-rotateY}deg)`;
});
cardMouseRange.addEventListener('mouseleave', () => {
card.style.transform = 'rotateX(0deg) rotateY(0deg)';
});
それでは解説します。
要素の取得
const cardMouseRange = document.querySelector(".card-hover-range");
const card = document.querySelector(".card");
cardMouseRangeは、マウス移動を検知する範囲になります。後にこの要素に対してmousemoveイベントを設定します。cardは、実際に傾けたいカード要素になります。
最大回転角度
const MaxRotate = 30;
MaxRotateは、後の計算で使用するカードが傾く最大の角度を設定してます。この値を変更することで、カードが傾く範囲を変更できます。このデモでは30度に設定しています。
イベントの設定
cardMouseRange.addEventListener('mousemove', (e) => {
const rect = card.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = (e.clientY - rect.top) / rect.height;
const rotateX = (0.5 - y) * MaxRotate;
const rotateY = (0.5 - x) * MaxRotate;
card.style.transform = `rotateX(${rotateX}deg) rotateY(${-rotateY}deg)`;
});
cardMouseRange.addEventListener('mouseleave', () => {
card.style.transform = 'rotateX(0deg) rotateY(0deg)';
});
cardMouseRangeにmousemoveイベントを設定して、マウスが動くたびにカードを傾けます。mouseleaveイベントでカードを元に戻します。
const x = (e.clientX - rect.left) / rect.width;
const y = (e.clientY - rect.top) / rect.height;
xとyは、マウスの位置をカードの中心からの相対位置に変換しています。
e.clientX/e.clientY: マウスの現在のX/Y座標rect.left/rect.top: カードの左上の座標rect.width/rect.height: カードの幅/高さ
このように計算することで、カード内のマウスの位置を0~1の範囲に変換します!
const rotateX = (0.5 - y) * MaxRotate;
const rotateY = (0.5 - x) * MaxRotate;
中心(0.5, 0.5)からどれだけ離れているかで傾き度合いを決めます。
(0.5 - y); 上に行くと正になり、下に行くと負の値になる。(0.5 - x); 左に行くと正になり、右に行くと負の値になる。
計算したものにMaxRotateをかけて、角度に変換します。
card.style.transform = `rotateX(${rotateX}deg) rotateY(${-rotateY}deg)`;
最後に計算した角度を、カードに適用します。rotateYにマイナスをつけているのは、マウス移動と回転方向が一致するようにするためです。
ホバーが外れたら、mouseleaveイベントでrotateを0にして、カードの角度を元に戻しましょう!







