LoginSignup
10
7

【CSS】ホバーすると立体的にアニメーションするカードを作る

Last updated at Posted at 2022-12-06

はじめに

みなさんは、どんなトレーディングカードゲームをやったことがありますか?

僕が触れたことがあるトレーディングカードゲームは、遊戯王デュエマポケカくらいですが、他にも、1993年からあるマジック:ザ・ギャザリングや最近のワンピース などなどいろいろなトレーディングカードゲームが存在します。

ただ、web上でトレーディングカードゲームのカードを表現しようとしても画像で表現することになり、立体感に欠け物足りない感じです。

今回は、そんなトレーディングカードゲームのカードを立体感に見るように、CSSとJavaScriptを使って、ホバーすると立体的にアニメーションするカードを作っていこうと思います。

完成形

完成形は、↓こんな感じです。

See the Pen 3D Card by でぐぅー | Qiita (@sp_degu) on CodePen.

hoverすると、マウスの位置に合わせて、カードが手前側に出ているよう見えるアニメーションにすることで、立体的にアニメーションするように表現しています。

また、CSSのプロパティの観点では、preserve-3dで、3Dに回転させて、画像を translate を使ってずらすことで、立体的にアニメーションして見えるように表現しています。

詳しい作り方は、これから解説していきます。

作り方

1. 構成を理解する

まずは、今回作成する立体的にアニメーションして見えるような表現の構成解説していきます。

image1.png

立体的にアニメーションして見えるような表現は、↑このように transform-style: preserve-3d;で、X軸とY軸を回転させることで、それっぽくしています。

ただ、transform-style: preserve-3d;だけを動かすと、回転方向がわからなくなるため、
回転に合わせて、画像の位置を調整する必要があります。

2. HTMLを作成する

1の構成になるように、HTMLの構造を以下のように作成していきます。

sample.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 に合わせて、画像の見える位置を変えられるように、形を整えて行きます。

sample.css
/*画像を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. マウスの位置に応じた、アニメーションを作成する

カード内のマウスの位置を取得する

sample.js
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属性に定義して、います。

以下の画像のように計算しています。
image4.png

カードがマウスの位置に応じて回転するようにする

sample.css
.card-wrapper:hover {
  transform:
    rotateX(calc((var(--ratio-x) - 0.5) * 50deg))
    rotateY(calc((var(--ratio-y) - 0.5) * -50deg));
}

.card-wrapper は、マウスポインターの位置に応じて、rotateXrotateY でカードを回転させています。
ホバーしている位置を手前側に持ってきたいので、以下のような数式になります。

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°

画像がマウスの位置に応じて移動するようにする

sample.css
.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)のフォローをお願いします。

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7