0
0

DIVをスムーズに追加するアニメーション

Posted at

1. はじめに

div要素をスムーズに追加するアニメーションを作りたくて、少し調査しました。

ソースは下記のitem_insert。(ほかのcssの練習をすることができるように、適当に大きな名前にしてあります。)

2. 課題

下記のように、黄色の内側に青があるという包含関係にあるDIV要素に対して、box1のさらに上へbox2、box3・・・と追加していくことを考えます。

image.png

このときbox2を追加したら、box2は上から降りてきて、box0とbox1は下に押し出される、というアニメーションを作りたいです。

こうかなーと適当にやると、box2を追加したとき、すでにあるbox0とbox1が最終的な位置に瞬間移動してしまいます。その押し出されるアニメーションをどうやるか。

3. 解決方法

結果的にこういう方法にしました。

See the Pen Untitled by yoichiro ikeda (@yo16) on CodePen.

3.1. 解決方法の概要

div要素を追加したら、上方向に瞬間的に飛ばします。CSSとしては、topにマイナス値を入れます。そのあとtopをゼロにします。CSSのtransitionを使って、マイナス→ゼロの変化は時間をかけることで、アニメーションで降りてきます。

3.2. 工夫した点

ポイントが3つあります。

1つ目は、CSSのtopの値を更新するタイミング。追加したときのtopのマイナス値への変化時にはtransitionは使わず、ゼロにするときには生かしたいです。なので、それぞれ生かしたいときに設定し、使いたくないときにはゼロ秒にしてます。

// 追加した直後の、マイナスの位置設定
function initializeMoveBoxes() {
    const boxes = document.querySelectorAll(".box");
    boxes.forEach(box => {
        box.style.top = `${initial_top}px`;
        box.style.transition = "top 0s";        // マイナス位置に、すぐ変更してほしい
    });
}

// じんわりと移動した結果の位置設定
function smoothMoveBoxes() {
    const boxes = document.querySelectorAll(".box");
    boxes.forEach(box => {
        box.style.top = "0px";
        box.style.transition = "top 0.5s ease";    // 0pxに、じんわりと変更してほしい
    });
}

2つ目は、topへの値の代入を上から順番に連続的に呼ぶだけだと、最後に入れた値になってしまって、transitionが効かないです。なのでsetTimeout()を使って、非同期でちょっと後に呼び出していること。こうすることで、2回目のtransitionが効きます。

initializeMoveBoxes();
setTimeout(()=>{smoothMoveBoxes();}, 10);  // 10ms後に非同期呼び出し

3つ目は、初期位置の座標値。heightpaddingbordermarginの関係で、上へずらす座標値が変わります。ちょっとでも間違ってると、ひっかかったような動作になってしまいます。marginは要素と要素の間の距離なので1カウント、それ以外は2カウント。CSSに合わせてJavaScriptでconstで定義して計算してます。忘れないように。。

const box_height = 32;
const box_padding = 10;
const box_border = 8;
const box_margin = 5;
const initial_top = (-1)*(
    box_height + 
    box_padding *2 + 
    box_border *2 + 
    box_margin
);

4. まとめ

アニメーションのライブラリを使ったいい方法があるかもしれないですが、こういう書き方を編み出すのも勉強になるし、読み込むコード量は少ないはずです。位置調整のために数字をいじらないといけないことになったものの、一応ロジックで定義できたし、position:absoluteでやらないといけないかも・・嫌だ・・・とずっと思いつつ、回避でできたので、自分的には及第点です。

JavaScriptとcssで、高さの数字とかを二重で持っちゃってる部分は、JavaScriptからcssを設定すればいいと思います。ここではわかりやすいようにしてあるのと、実際に使うときは、汎用的に書かず、数字直打ちでもいいかもしれない。

あとアニメーションの技術は、検索する方法が難しいですね。今回の課題をググるにはどうしたらいいか、なかなか苦戦しました。いい方法があったら是非コメント欄で教えてください!

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