はじめに
- 第13回は、JavaScriptを使用してクリックによるアニメーションの拡大・縮小
- 第14回は、CSSを使用して
hover
によるアニメーションの拡大・縮小
を試しました。
第14回のCSSのanimation-name
を使用して、CSSだけでクリックしてアニメーションをしようと思いましたが、CSSにはクリックに対する疑似クラスがないことに気づき断念しました。
activve
を使用すればクリックになるのかと思ったのですが、active
は、要素を押し続けている状態だけ動作するものであり、クリックではなかったので、期待通りの動作ではありませんでした。
今回は、CSSに加えてJavaScriptを使用することで、hover
ではなく、クリックによるアニメーションを試したいと思います。
今回実施する内容
JavaScriptのanimate
で作成するクリックによる拡大と、JavaScriptとCSSのanimation-name
で作成するクリックによる拡大を実施します。
ソースコード(Git Hub)
環境
OS: Windows 11 JP (64bit)
Microsoft Edge:バージョン 123.0.2420.65 (公式ビルド) (64 ビット)
参考
用語
JavaScriptのanimate
で作成するクリック拡大とJavaScriptとCSSのanimation-name
で作成するクリックによる拡大
clickAnimation.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Click Animation</title>
<link rel="stylesheet" href="clickAnimation.css" type="text/css">
<script src="clickAnimation.js" defer></script>
</head>
<body>
<div id="scale1">拡大(javascript)はここをクリック</div>
<div id="scale2">拡大(javascript+css)はここをクリック</div>
</body>
</html>
clickAnimation.js
document.getElementById("scale1").addEventListener("click", () => {
clickScaleIn("scale1");
});
document.getElementById("scale2").addEventListener("click", () => {
clickScaleIn2("scale2");
});
function clickScaleIn(name) {
const animation = document.getElementById(name).animate(
[
//キーフレーム
{transform: 'scale(1)'},
{transform: 'scale(2)'}
],
{
//タイミングオプション
duration: 1000,
fill: "forwards"
}
);
}
function clickScaleIn2(name) {
document.getElementById(name).classList.remove("scaleIn");
setTimeout(() => {
document.getElementById(name).classList.add("scaleIn");
},1);
}
clickAnimation.css
#scale1 {
background-color:yellow;
position: absolute;
width: 300px;
height: 100px;
top: 100px;
left: 200px;
}
#scale2 {
background-color:red;
position: absolute;
width: 300px;
height: 100px;
top: 300px;
left: 200px;
}
.scaleIn {
animation-duration: 1000ms;
animation-fill-mode: forwards;
animation-name: scaleIn;
}
@keyframes scaleIn {
/*キーフレーム*/
from
{transform:scale(1)}
to
{transform:scale(2)}
}
clickAnimation.htmlの説明
<body>
<div id="scale1">拡大(javascript)はここをクリック</div>
<div id="scale2">拡大(javascript+css)はここをクリック</div>
</body>
第13回で 拡大 として作成した内容と同じです。
1つ目のdiv
は、第13回の時に作成したJavaScriptで拡大する要素です。
2つ目のdiv
は、JavaScriptとCSSで拡大する要素です。
clickAnimation.jsの説明
document.getElementById("scale1").addEventListener("click", () => {
clickScaleIn("scale1");
});
document.getElementById("scale2").addEventListener("click", () => {
clickScaleIn2("scale2");
});
-
1つ目は、htmlの1つ目の
div
要素(id:scale1
)をクリックした時にclickScaleIn("scale1")
を実施するイベントリスナーを追加します。 -
2つ目は、htmlの2つ目の
div
要素(id:scale2
)をクリックした時にclickScaleIn2("scale2")
を実施するイベントリスナーを追加します。
function clickScaleIn(name) {
const animation = document.getElementById(name).animate(
[
//キーフレーム
{transform: 'scale(1)'},
{transform: 'scale(2)'}
],
{
//タイミングオプション
duration: 1000,
fill: "forwards"
}
);
}
第13回で作成した拡大のソースと同じです。
- htmlの1つ目の
div
要素(id:scale1
)をクリックした時の動作を規定しています。
キーフレームは、「キーフレームの開始」と「キーフレームの終了」のscale(1)とscale(2) を設定し、「キーフレームの開始」は等倍で、「キーフレームの終了」は、2倍拡大します。
タイミングオプションは、- duration: 1000でアニメーションは1秒間
- fill: "forwards"
- で、最後のアニメーションを保持であり、この例では2倍に拡大した状態が維持されます。
クリックしてアニメーション終了後に再度クリックすると、再度等倍に戻って、2倍まで拡大します。
function clickScaleIn2(name) {
document.getElementById(name).classList.remove("scaleIn");
setTimeout(() => {
document.getElementById(name).classList.add("scaleIn");
},1);
}
document.getElementById("scale2").classList.remove("scaleIn");
では、2つ目のdiv
要素(id: scale2
)からscaleIn
のクラスを削除します。
scaleIn
のクラスが追加されていない場合は削除されず、追加されている場合は削除されます。
クラスを追加してアニメーションが終わった後、再度クリックしても、元の拡大前の状態に戻って拡大しなおすことはない ため、要素から追加のクラスを削除することで元の状態に戻します。
また、最初にこのクラスを削除することで、要素をクリックして拡大アニメーション中にクリックする場合、拡大中から元の状態に戻して拡大することもできます。
この動作は、JavaScriptで、fill: "forwards"
を設定したときと同じ動作です。
次はsetTimeout(() => {...},1);
の部分についてです。
setTimeout()は、以下の通り記載されています。
グローバルの setTimeout() メソッドは、時間切れになると関数または指定されたコードの断片を実行するタイマーを設定します。
構文
JSsetTimeout(code) setTimeout(code, delay) setTimeout(functionRef) setTimeout(functionRef, delay) setTimeout(functionRef, delay, param1) setTimeout(functionRef, delay, param1, param2) setTimeout(functionRef, delay, param1, param2, /* … ,*/ paramN)
引数
functionRef
タイマーが満了した後に実行する関数。
code
関数の代わりに文字列を含める代替構文も許容されており、タイマーが満了したときに文字列をコンパイルして実行します。 eval() の使用にリスクがあるのと同じ理由で、この構文は推奨しません。
delay
省略可
指定した関数やコードを実行する前に待つタイマーの時間をミリ秒 (1/1000 秒) 単位で指定します。この引数を省略すると値 0 を使用しますので "直ちに" 実行する、より正確に言えばできるだけ早く実行することを意味します。なお、どちらの場合も、実際の遅延が想定より長くなることがあります。後述する遅延が指定値より長い理由をご覧ください。
また、値が数値でない場合、暗黙のうちに型強制が行われ、数値に変換されることにも注意してください。これは予期しない、驚くべき結果につながる可能性があります。例として、delay の値が数値でない場合は暗黙に数値に強制されるを参照してください。
param1
, …,paramN
省略可
タイマーが満了したときに、 functionRef で指定された関数に渡す追加の引数です。
ということですので、setTimeout(() => {...},1);
の関数記載箇所にタイマー満了後の動作を記載します。タイマー(delay
)の値は、1msを設定します。
これによって、scaleIn
のクラスの削除を実施した1ms後に関数を実施するようにします。
関数では、scaleIn
のクラス追加をします。
クラスの具体的な内容は、clickAnimation.css
に記載しますが、実施内容は、第13回で作成した拡大のソースと同じです。
setTimeout
を使用したのは、JavaScriptは非同期プログラミングであるため、setTimeout
を設定せずに、「クラスの削除」、「クラスの追加」を設定した場合、「クラスの削除」が動作しないまま、「クラスの追加」が発生しているような動作となり、期待通り動作しないためです。
タイマー(delay
)の値は、最小値を1msで最小値で動作しましたが、もしうまく動作しないことがあるなら10ms程度でもぱっと見動作的には遅延は感じなかったため、少し伸ばすのはありそうです。
clickAnimation.cssの説明
.scaleIn {
animation-duration: 1000ms;
animation-fill-mode: forwards;
animation-name: scaleIn;
}
@keyframes scaleIn {
/*キーフレーム*/
from
{transform:scale(1)}
to
{transform:scale(2)}
}
第14回で 拡大 として作成した内容と同じです。
2つ目のdiv
を1倍から2倍に1秒間で拡大します。
animatin-fill-mode
はforward
を設定し、アニメーション終了後は最後の状態を保持します。
おわりに
JavaScriptのanimate
とJavaScriptとCSSのanimation-name
で、クリックした時に拡大するアニメーションを作りました。
作ってみて気づいたのですが、同じ1秒のアニメーションなのですが、JavaScriptだけの場合はちょうど1秒くらいで、JavaScriptとCSSの組み合わせでは若干早く800ms~900msくらいでアニメーションしました。
この違いは処理の問題なんだろうか?