0
0

第15回 JavaScript クリックで拡大(JavaScript+CSS)

Last updated at Posted at 2024-05-02

はじめに

  • 第13回は、JavaScriptを使用してクリックによるアニメーションの拡大・縮小
  • 第14回は、CSSを使用してhoverによるアニメーションの拡大・縮小

を試しました。

第14回のCSSのanimation-nameを使用して、CSSだけでクリックしてアニメーションをしようと思いましたが、CSSにはクリックに対する疑似クラスがないことに気づき断念しました。
activveを使用すればクリックになるのかと思ったのですが、activeは、要素を押し続けている状態だけ動作するものであり、クリックではなかったので、期待通りの動作ではありませんでした。

今回は、CSSに加えてJavaScriptを使用することで、hoverではなく、クリックによるアニメーションを試したいと思います。

今回実施する内容

JavaScriptのanimateで作成するクリックによる拡大と、JavaScriptとCSSのanimation-nameで作成するクリックによる拡大を実施します。
Scale_CSS.gif

ソースコード(Git Hub)

環境

OS: Windows 11 JP (64bit)
Microsoft Edge:バージョン 123.0.2420.65 (公式ビルド) (64 ビット)

参考

setTimeout()

用語

JavaScriptのanimateで作成するクリック拡大とJavaScriptとCSSのanimation-nameで作成するクリックによる拡大

clickAnimation.html
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
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
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() メソッドは、時間切れになると関数または指定されたコードの断片を実行するタイマーを設定します。

構文

JS
setTimeout(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-modeforwardを設定し、アニメーション終了後は最後の状態を保持します。

おわりに

JavaScriptのanimateとJavaScriptとCSSのanimation-nameで、クリックした時に拡大するアニメーションを作りました。
作ってみて気づいたのですが、同じ1秒のアニメーションなのですが、JavaScriptだけの場合はちょうど1秒くらいで、JavaScriptとCSSの組み合わせでは若干早く800ms~900msくらいでアニメーションしました。
この違いは処理の問題なんだろうか?

0
0
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
0
0