ポケモンの能力アップみたいなアニメーションを CSS で作った
やったこと
ポケモンの能力アップしたときのようなエフェクトを CSS で作りました。
DS 作品(ダイヤモンド・パールとか)までのアニメーションを意識しています。
注意
以下のブラウザで動作することを確認しています。いずれも 2022/9/26 時点での最新版です。
その他のブラウザでは動かない可能性があります。
- Google Chrome Version 105.0.5195.127
- Mozilla Firefox Version 105.0.1
作り方
素材を入手する
PokeAPI を使って素材を入手しました。
画像を手に入れたい欲しいポケモンの図鑑番号(今回はリザードンの6)を使って検索すると、特性や種族値などの情報を取得できます。
今回は、 sprites.front_default
の画像データを使います。
次のように div
要素に background
プロパティを使って画像を指定します。
<div class="pokemon no6"></div>
.pokemon {
height: 96px;
width: 96px;
}
.no6 {
background: no-repeat url(https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/6.png);
}
素材に合わせたエフェクトを表示できるようにする
css の mask-image
を使います。
div
要素を追加し、mask-image
プロパティを使ってエフェクトのマスクに使う画像を指定します。
<div class="pokemon no6">
<div class="effect"></div>
</div>
.effect {
height: 100%;
width: 100%;
}
.no6 .effect {
-webkit-mask-image: url(https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/6.png);
mask-image: url(https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/6.png);
}
試しに次のような指定を追加すると、画像にぴったり合うように表示範囲がマスクされていることが確認できます。
.effect {
background-color: blue;
}
エフェクトを表示する
静止した状態で作る
能力アップの時に出るギザギザ模様を表現します。
effect
クラスの子要素として、模様を表示する effect-image
クラスを持つ要素を追加します。
effect-image
クラスに repeating-linear-gradient
を使って次のように指定すると、斜めの縞模様が表示されます。
色やサイズは雰囲気で指定しています。
<div class="pokemon no6">
<div class="effect">
<div class="effect-image"></div>
</div>
</div>
.effect-image {
background-image: repeating-linear-gradient(
60deg,
red 0,
orange 2px,
white 4px,
orange 6px,
red 8px
);
}
この縞模様を、一部を反転して表示するとギザギザ模様を作ることができます。
反転する部分を作るために、横方向に div
要素をいくつか並べます(とりあえず8こ)。 background-image
を effect-image
クラスの子要素で指定し、かつ偶数番目を反転させるとギザギザ模様になります。
反転には、 transoform
プロパティを使います。
<div class="pokemon no6">
<div class="effect">
<div class="effect-image">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
.effect-image {
display: flex;
}
.effect-image div {
width: 12.5%;
height: 100%;
background-image: repeating-linear-gradient(
60deg,
red 0,
orange 2px,
white 4px,
orange 6px,
red 8px
);
}
.effect-image div:nth-child(even) {
transform: scale(-1, 1);
}
アニメーションで上昇させる
animation
と keyframes
を使って上昇するアニメーションを作ります。
また、画像の上昇分に合わせて、 effect-image
の高さを大きくしておきます。
@keyframes up {
from {
transform: translate(0, 0);
}
to {
transform: translate(0, -100px);
}
}
.effect-image {
height: calc(100% + 100px);
animation: up 1.3s ease-out 0s infinite;
}
ボタンを追加
好きなタイミングでアニメーションを動かすためにボタンを追加します。
ボタンをクリックしてアニメーションが動くように、次のように実装しました。
- ボタンがクリックされたタイミングで、
effect-up
クラスを追加 -
effect-up
クラスが追加された時、アニメーションを一度だけ表示 - アニメーションが終了したら
effect-up
クラスを削除
また、次のような調整も行いました。
- アニメーションが動いていないときはエフェクトが見えないようにする
- アニメーションの最中で「透明→半透明→透明」とエフェクトの見え方を変化させる
<div id="pokemon-no6" class="pokemon no6"> <!-- id を追加 -->
<div class="effect">
<div class="effect-image">
(略)
<button id="button-up">up</button>
@keyframes up {
0% {
transform: translate(0, 0);
opacity: 0;
}
20% {
opacity: 0.5;
}
70% {
opacity: 0.5;
}
100% {
transform: translate(0, -100px);
opacity: 0;
}
}
.effect-image {
opacity: 0;
}
.effect-up .effect-image {
animation: up 1.3s ease-out;
}
const effect = document.getElementById("pokemon-no6").children[0];
effect.addEventListener("animationend", function () {
effect.classList = ["effect"];
});
document.getElementById("button-up").onclick = function () {
effect.classList.add("effect-up");
};
バリエーションを増やす
能力ダウンした場合も同様に実装したら完成です。
能力アップとの違いは色とアニメーションの向きだけです。
CSS のカスタムプロパティを使うと簡単に色を変更させられます。
.effect-up {
--color-1: red;
--color-2: orange;
--color-3: white;
}
.effect-down {
--color-1: navy;
--color-2: aqua;
--color-3: white;
}
.effect-image {
background-image: repeating-linear-gradient(
60deg,
var(--color-1) 0,
var(--color-2) 2px,
var(--color-3) 4px,
var(--color-2) 6px,
var(--color-1) 8px
);
}
あとは気が済むまで色やサイズを微調整したら完成です。
まとめ
使った主要な技術は以下のとおりです。
-
mask-image
を使った画像のマスク処理 -
repeating-linear-gradient
を使ったパターン画像 -
animation
とkeyframes
を使ったアニメーション
Discussion
アイデアが最高で、おもしろい記事でした!
構成要素はシンプルなのにかなりそれっぽくてすごいです 🤩
反転する部分を作るところでdivを並べて作られていますが、
mask-imageを使えば
::before
,::after
だけで作れそうだと思い、フォークして作ってみました。CSSで作っておくと、列の数をCSS変数 (
--effect-lines
) で制御できてイイ感じです。ご参考まで!
コメントありがとうございます。
ギザギザ模様がちょうど
before
とafter
で表現できるんですね。mask-image / linear-gradient
とtransform/scaleX
の使い方がうまくて勉強になりました!