はじめに
みなさんは、どんなトレーディングカードゲームをやったことがありますか?
僕が触れたことがあるトレーディングカードゲームは、遊戯王、デュエマ、ポケカくらいですが、他にも、1993年からあるマジック:ザ・ギャザリングや最近のワンピース などなどいろいろなトレーディングカードゲームが存在します。
ただ、web上でトレーディングカードゲームのカードを表現しようとしても画像で表現することになり、立体感に欠け物足りない感じです。
今回は、そんなトレーディングカードゲームのカードを立体感に見るように、CSSとJavaScriptを使って、ホバーすると立体的にアニメーションするカードを作っていこうと思います。
完成形
完成形は、↓こんな感じです。
See the Pen 3D Card by でぐぅー | Qiita (@sp_degu) on CodePen.
hoverすると、マウスの位置に合わせて、カードが手前側に出ているよう見えるアニメーションにすることで、立体的にアニメーションするように表現しています。
また、CSSのプロパティの観点では、preserve-3d
で、3Dに回転させて、画像を translate
を使ってずらすことで、立体的にアニメーションして見えるように表現しています。
詳しい作り方は、これから解説していきます。
作り方
1. 構成を理解する
まずは、今回作成する立体的にアニメーションして見えるような表現の構成解説していきます。
立体的にアニメーションして見えるような表現は、↑このように transform-style: preserve-3d;
で、X軸とY軸を回転させることで、それっぽくしています。
ただ、transform-style: preserve-3d;
だけを動かすと、回転方向がわからなくなるため、
回転に合わせて、画像の位置を調整する必要があります。
2. HTMLを作成する
1の構成になるように、HTMLの構造を以下のように作成していきます。
<div class="card-wrapper">
<img class="card image" src="../../image.jpeg" />
</div>
画像が見える位置が :hover
に合わせて変わるため、
<div class="card-wrapper">
で <img>
をラップします。
そのため、3Dに回転する要素は、<div class="card-wrapper">
になります。
3. カードの形を整える
次に、<img>
にscaleをかけて、<div class="card-wrapper">
から見えない部分を作り、
:hover
に合わせて、画像の見える位置を変えられるように、形を整えて行きます。
/*画像をcard-wrapperより大きくする*/
.image {
scale: 1.2;
}
/*形を整える*/
.card {
aspect-ratio: 3 / 4;
box-shadow: 0px 4px 8px rgba(0, 0, 0, .2);
height: 100%;
position: absolute;
width: 100%;
}
.card-wrapper {
border-radius: 4.5% / 3.5%;
aspect-ratio: 3 / 4;
display: grid;
height: calc(100% - 32px);
max-width: 100%;
overflow: hidden;
position: absolute;
}
/*真ん中に持ってきている*/
body {
background-color: #212529;
display: grid;
height: calc(100vh - 32px);
margin: 0;
padding: 16px;
place-items: center;
position: relative;
width: calc(100% - 32px);
transform-style: preserve-3d;
}
4. マウスの位置に応じた、アニメーションを作成する
カード内のマウスの位置を取得する
console.clear()
const CARD = document.querySelector('.card-wrapper')
const UPDATE = ({ x, y }) => {
const BOUNDS = CARD.getBoundingClientRect()
const posX = x - BOUNDS.x
const posY = y - BOUNDS.y
const ratioX = posX / BOUNDS.width
const ratioY = posY / BOUNDS.height
CARD.style.setProperty('--ratio-x', ratioX)
CARD.style.setProperty('--ratio-y', ratioY)
}
document.body.addEventListener('pointermove', UPDATE)
addEventListener
の 'pointermove'
で、マウスポインターの位置を取得します。
また、マウスポインターがカード内のどの位置にあるのかをいい感じに計算しした値を
cssの変数(--ratio-x
・--ratio-y
)で使えるように、.card-wrapper
のstyle属性に定義して、います。
カードがマウスの位置に応じて回転するようにする
.card-wrapper:hover {
transform:
rotateX(calc((var(--ratio-x) - 0.5) * 50deg))
rotateY(calc((var(--ratio-y) - 0.5) * -50deg));
}
.card-wrapper
は、マウスポインターの位置に応じて、rotateX
・rotateY
でカードを回転させています。
ホバーしている位置を手前側に持ってきたいので、以下のような数式になります。
X軸 → calc((var(--ratio-x) - 0.5) * 50deg)
Y軸 → calc((var(--ratio-y) - 0.5) * -50deg)
-
--ratio-x / --ratio-y
- マウスポインターの位置がカードのX軸/Y軸の中で左上の位置からそれぞれ何%の位置になるか
- 値:
0
~1
-
var(--ratio-x) - 0.5 / var(--ratio-y) - 0.5
- マウスポインターの位置がカードのX軸/Y軸の中で中心から何%の位置になるか
- 値:
-0.5
~0.5
-
(var(--ratio-x) - 0.5) * 50deg / (var(--ratio-y) - 0.5) * 50deg
- 最大の角度を25°になるようにしています。
- Y軸は、回転方向を逆にするため、
-50deg
をかけています。 - 値:
-25°
~25°
画像がマウスの位置に応じて移動するようにする
.image:hover {
translate:
calc((var(--ratio-x) - 0.5) * -5%)
calc((var(--ratio-y) - 0.5) * -5%);
}
マウスの位置に応じて、画像の位置をずらすことで、回転方向が分かりやすくなるため、<img>
を以下のような数式で移動させています。
X軸 → calc((var(--ratio-x) - 0.5) * -5%)
Y軸 → calc((var(--ratio-y) - 0.5) * -5%)
-
--ratio-x / --ratio-y
- マウスポインターの位置がカードのX軸/Y軸の中で左上の位置からそれぞれ何%の位置になるか
- 値:
0
~1
-
var(--ratio-x) - 0.5 / var(--ratio-y) - 0.5
- マウスポインターの位置がカードのX軸/Y軸の中で中心から何%の位置になるか
- 値:
-0.5
~0.5
-
(var(--ratio-x) - 0.5) * -5% / (var(--ratio-y) - 0.5) * -5%
- 移動方向を逆にするため、
-5%
をかけています。 - 最大の移動が2.5% になるようにしています。
- 値:
-2.5%
~2.5%
- 移動方向を逆にするため、
完成
すると、このようにマウスの位置に合わせて、カードが立体的にアニメーションしているようにに表現しています。
See the Pen 3D Card by でぐぅー | Qiita (@sp_degu) on CodePen.
まとめ
今回は、トレーディングカードゲームのカードを立体感に見るように、CSSとJavaScriptを使って、ホバーすると立体的にアニメーションするカードを使って作りました。
構造としては、シンプルですが、計算式が直感で理解するのは難しく感じます。
そのため、もしお時間あれば手元で計算式の値を変えてみていただくと、理解が深まると思います。
この表現がトレーディングカードゲームのカードのweb通販のサイトや、クレジットカードの比較アフィリエイトサイトとかで、使われると見るだけで楽しいものになるのかなとかと感じました。
またこの記事のカードを光らせるアニメーションを追加するとなおクオリティが上がると思います。
最後まで読んでくださってありがとうございます!
普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。