アニメーションしながら選択肢を絞り込むソート機能

アニメーションしながら選択肢を絞り込むソート機能

カテゴリーの絞込みを、アニメーションを加えて表現しています。

カテゴリを選択すると、一旦全部がアニメーションしながら消え、選択されたカテゴリのものだけがアニメーションしながら表示されます。

デモ

実装方法は、カテゴリ選択のボタンに仕込んであるクラス名と、絞り込まれる側の要素と同じクラス名を付けるだけです。

ソースコードと解説

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);
}

とかもいいですね。