アニメーションしながら選択肢を絞り込むソート機能
- 2019.05.06
- javascript+css
- javascript, 脱jQuery
カテゴリーの絞込みを、アニメーションを加えて表現しています。
カテゴリを選択すると、一旦全部がアニメーションしながら消え、選択されたカテゴリのものだけがアニメーションしながら表示されます。
実装方法は、カテゴリ選択のボタンに仕込んであるクラス名と、絞り込まれる側の要素と同じクラス名を付けるだけです。
ソースコードと解説
html
<dl> <dt>選択肢:</dt> <dd class="red">赤</dd> <dd class="blue">青</dd> <dd class="green">緑</dd> <dd class="lightblue">水色</dd> <dd class="yellow">黄色</dd> <dd class="purple">紫</dd> <dd class="orange">オレンジ</dd> <dd class="yellowgreen">黄緑</dd> <dd class="pink">ピンク</dd> </dl> <div id="boxes"> <div class="lightblue"></div> <div class="yellow"></div> <div class="purple"></div> <div class="orange"></div> <div class="red"></div> <div class="yellowgreen"></div> <div class="blue"></div> <div class="pink"></div> <div class="green"></div> <div class="yellowgreen"></div> <div class="yellow"></div> <div class="lightblue"></div> <div class="orange"></div> <div class="purple"></div> <div class="yellowgreen"></div> <div class="lightblue"></div> <div class="pink"></div> <div class="yellowgreen"></div> <div class="blue"></div> <div class="purple"></div> <div class="yellow"></div> </div>
css
dt { font-weight: bold; display: inline-block; } dd { display: inline-block; text-decoration: underline; cursor: pointer; } #boxes div { width: 150px; height: 150px; margin: 10px; display: inline-block; transition: .5s; } #boxes .lightblue { background-color: lightblue;} #boxes .red { background-color: red;} #boxes .green { background-color: green;} #boxes .yellow { background-color: yellow;} #boxes .yellowgreen { background-color: yellowgreen;} #boxes .pink { background-color: pink;} #boxes .orange { background-color: orange;} #boxes .purple { background-color: purple;} #boxes .blue { background-color: blue;} .hidden { transform: scale(0, 0); }
アニメーションは css で指定しています。
.hidden { transform: scale(0, 0); }
この .hidden を付けたりはずしたりすることで、アニメーションさせています。
#boxes div { ~ 略 ~ transition: .5s; }
要素には transition を指定しておきます。
「0.5秒かけてアニメーション」という指定になります。
javascript
var btns = document.querySelectorAll('dd'); // 選択肢のボタン var parent = document.getElementById('boxes'); // 要素を囲う親要素 var box = document.querySelectorAll('#boxes div'); // それぞれのBOX var selected; // 選択されたクラスを入れるための変数 var selectLi = []; // 選択されたboxを入れておくための配列 var first = true; // 1回目かどうか for (var i = 0; i < btns.length; i++) { // 選択肢のクリックがあったら btns[i].addEventListener('click', function () { // 1回目の場合の処理 if (first) { // 選択されたクラス名を取得 selected = this.className; // 一旦全部をアニメーションで消し for (var j = 0; j < box.length; j++) { box[j].classList.add('hidden'); // 選択されたクラスが付いているものだけを selectLi の配列へ if(box[j].classList.contains(selected)) { selectLi.push(box[j]); } } // 時間差で処理。消すときのアニメーションを待つため setTimeout(function () { // 親要素内の要素をすべて削除 for (var j = 0; j < box.length; j++) { parent.removeChild(box[j]); } // 親要素に選択されたboxを追加 for (var j = 0; j < selectLi.length; j++) { parent.appendChild(selectLi[j]); } // 時間差で処理。アニメーションをさせたいため。 setTimeout(function () { // hiddenクラスを削除し、アニメーションで表示 for (var j = 0; j < selectLi.length; j++) { selectLi[j].classList.remove('hidden'); } },100); }, 500); // 500ミリ秒後に設定。アニメーションの時間 first = false; // 1回目かどうかのフラグにfalseを代入 } // 2回目以降の処理 else { // 選択されたboxをアニメーションで消す。 for (var j = 0; j < selectLi.length; j++) { selectLi[j].classList.add('hidden'); } // 選択されたボタンのクラスを取得 selected = this.className; // 選択された要素を入れるための配列を一旦空にして selectLi = []; // 時間差で処理 setTimeout(function () { // 親要素に一旦もとの要素全部追加して for (var j = 0; j < box.length; j++) { parent.appendChild(box[j]); // 選択されたboxを selectLi 配列へ if(box[j].classList.contains(selected)) { selectLi.push(box[j]); } } // 親要素内の要素を全部消し、 for (var j = 0; j < box.length; j++) { parent.removeChild(box[j]); } // 選択された要素だけを親要素に追加 for (var j = 0; j < selectLi.length; j++) { parent.appendChild(selectLi[j]); } // 時間差で処理。アニメーションのため setTimeout(function () { for (var j = 0; j < selectLi.length; j++) { // hiddenクラスを削除して、アニメーションで表示 selectLi[j].classList.remove('hidden'); } },100); }, 500); } }); }
ソートが1度目かそれ以外かで処理を変えています。
1度ソートしてしまうと、要素の数が減ってしまうので、同じように処理をするとエラーになりました。
var first = true; // 1回目かどうか
この変数で、1度目かどうかを判別します。
まずは1度目の処理。
if (first) { // 選択されたクラス名を取得 selected = this.className; // 一旦全部をアニメーションで消し for (var j = 0; j < box.length; j++) { box[j].classList.add('hidden'); // 選択されたクラスが付いているものだけを selectLi の配列へ if(box[j].classList.contains(selected)) { selectLi.push(box[j]); } } // 時間差で処理。消すときのアニメーションを待つため setTimeout(function () { // 親要素内の要素をすべて削除 for (var j = 0; j < box.length; j++) { parent.removeChild(box[j]); } // 親要素に選択されたboxを追加 for (var j = 0; j < selectLi.length; j++) { parent.appendChild(selectLi[j]); } // 時間差で処理。アニメーションをさせたいため。 setTimeout(function () { // hiddenクラスを削除し、アニメーションで表示 for (var j = 0; j < selectLi.length; j++) { selectLi[j].classList.remove('hidden'); } },100); }, 500); // 500ミリ秒後に設定。アニメーションの時間 first = false; // 1回目かどうかのフラグにfalseを代入 }
流れとしては、
選択されたカテゴリのクラス名を取得
↓
一旦全部を非表示(.hidden をつける。)
↓
選択されたカテゴリのクラス名がついているものだけを別の配列 selectLiへ
↓
要素を削除し、選択されたものを新たに追加
↓
表示(.hidden クラスをとることでアニメーション)
↓
1度目かどうか判別するための変数に、falseを代入
という感じです。
2回目以降は、一旦全部消すのが selectLi となります。
else { // 選択されたboxをアニメーションで消す。 for (var j = 0; j < selectLi.length; j++) { selectLi[j].classList.add('hidden'); } // 選択されたボタンのクラスを取得 selected = this.className; // 選択された要素を入れるための配列を一旦空にして selectLi = []; // 時間差で処理 setTimeout(function () { // 親要素に一旦もとの要素全部追加して for (var j = 0; j < box.length; j++) { parent.appendChild(box[j]); // 選択されたboxを selectLi 配列へ if(box[j].classList.contains(selected)) { selectLi.push(box[j]); } } // 親要素内の要素を全部消し、 for (var j = 0; j < box.length; j++) { parent.removeChild(box[j]); } // 選択された要素だけを親要素に追加 for (var j = 0; j < selectLi.length; j++) { parent.appendChild(selectLi[j]); } // 時間差で処理。アニメーションのため setTimeout(function () { for (var j = 0; j < selectLi.length; j++) { // hiddenクラスを削除して、アニメーションで表示 selectLi[j].classList.remove('hidden'); } },100); }, 500); }
使い方
選択肢を <dd> で指定。
<dd class="red">赤</dd> <dd class="blue">青</dd> <dd class="green">緑</dd> <dd class="lightblue">水色</dd> <dd class="yellow">黄色</dd> <dd class="purple">紫</dd> <dd class="orange">オレンジ</dd> <dd class="yellowgreen">黄緑</dd> <dd class="pink">ピンク</dd>
<dd> でなくても良いですが、その場合は javascript の
var btns = document.querySelectorAll('dd');
を変更してあげて下さい。
選択肢には、それぞれクラスを設定しておきます。
選択肢に設定したクラスを、絞り込まれる側にも指定します。
<div class="lightblue"></div> <div class="yellow"></div> <div class="purple"></div> <div class="orange"></div> <div class="red"></div> <div class="yellowgreen"></div> <div class="blue"></div> <div class="pink"></div> <div class="green"></div> <div class="yellowgreen"></div> <div class="yellow"></div> <div class="lightblue"></div> <div class="orange"></div> <div class="purple"></div> <div class="yellowgreen"></div> <div class="lightblue"></div> <div class="pink"></div> <div class="yellowgreen"></div> <div class="blue"></div> <div class="purple"></div> <div class="yellow"></div>
これも <div> でなくてもOKです。
こちらは javascript の方を変更する必要はありません。
アニメーションのしかたは
.hidden { transform: scale(0, 0); }
を変えてあげれば、いろいろできます。
たとえば
.hidden { transform: scale(0, 1); }
とか
.hidden { transform: rotate(180deg); }
とかもいいですね。
-
前の記事
Bracketsのプラグインでminify化してくれないjavascriptの書き方 2019.04.24
-
次の記事
[javascriptエラー]Expected ‘case’ at column 5, not column 9. 2019.05.06