特定の要素をタイル状に表示させるJavaScript

動作デモ

jQueryで実装しています。

簡単な仕組みはとしては、

指定されたIDのUIタグの直下にあるLIタグをタイルのようにposition:absolute;で配置していきます。

全体の横幅とカラム数から、各カラムの横幅を計算。

タイルを配置する場所は、
X方向(left: Npx;)はカラムの横幅が固定なので、何番目のカラムかによって取得。
Y方向(top: Npx;)は各カラムのうち、縦幅が最も低い値がY方向になります。

とりあえずソース(きたなくてごめんなさい(ノД`)

※2011年7月16日 ソース変更
子要素がないと無限ループに入ってしまう不具合を修正しました。

※2011年7月12日 ソース変更
ランダムでに要素の表示させる方法を変更し、各要素の表示される間隔を一定にすることで、流れるように表示されていくようにしました。
また、表示アニメーションを変更できるようにしました。

$(function(){
/*
こんな感じで実行します。
この場合は、id="TILES"をターゲットに、3カラムで余白3px、
全てのアニメーションが終わるまで1000秒、表示方法はフェードインさせます。
*/
TILES("ul#TILES", 3, 3, 1000, "fadein");
});

var TILES = function(parent, clm, cellpadding, time, anime){
	/*
	ul#TILESを基準に、その直下のliタグをタイル状に表示させます。

	parent … 親要素のULタグ
	clm … カラムの数
	cellpadding … 要素ごとの余白(px)
	parent … 親要素のID
	time … 全ての要素を表示させるまでの時間
	anime … fadein | slidedown | cards
	*/

	/* default */
	if(clm == undefined || clm == 0) var clm = 3;
	if(cellpadding == undefined || cellpadding == 0) var cellpadding = 3;
	if(parent == undefined || parent == '') var parent = "ul#TILES";
	if(time == undefined) time = 600;
	if(anime == undefined) anime = "slidedown";

	// 親要素
	var pr = $(parent);
	// 子要素
	var ch = $(parent+'>li');
	// 親要素のcss変更
	pr.css("position","relative");
	// 子要素の数
	chMx = ch.length;

	//子要素があれば
	if(chMx > 0) {
		// 子要素のcss変更
		ch.css({"list-style":"none inside","padding":0,"overflow":"hidden","margin":cellpadding,"position":"absolute"});
		// 子要素を隠す
		ch.hide();

		// 変更するcss を格納
		var css = new Array();

		// 各列の高さを格納する配列
		var y = new Array();
		// カラムの数だけの配列作成
		for(var i = 0;i < clm;i++) {y[i] = 0;}

		var bW = pr.width();
		var cW = Math.floor(bW/clm);
		var	top = 0, // css:top
			left = 0, // css:left
			r = 0, // 改行のチェック
			c = 0; // 回数(カラム数ごとに初期化)
		//子要素をループ
		ch.each(
			function(i, elem){
				var eW = cW-cellpadding * 2;
				// 横幅の統一 : 縦幅の取得より先に実行(横幅を変えると縦幅が変動するため)
				$(elem).width(eW);
				// 縦幅の取得(余白も含める)
				var eH = $(elem).height()+(cellpadding * 2);

				var n = 0;
				// 全体の横幅を超えれば、改行フラグを立てる(1行目以降)
				if(cW + left > bW && r == 0) {
					r++;
				}
				// 1行目の処理
				if(r == 0) {
					y[c] += eH; // 各カラムの高さを配列に格納
				} else {
				// 2行目以降の処理
					// 高さ配列から、最小の高さを求める
					//縦幅が最も低いカラムを求める
					//最初に1つ目のカラムだけ取得
					left = 0;
					top = y[0];
					n = 0;
					for(var q = 0;q < clm;q++) {
						if(y[q] < top) {
							left = q * cW;
							top = y[q];
							n = q;
						}
					}
					//求めたカラムの高さを更新
					y[n] += eH;
				}

				// 時間差を発生させる
				// 計算適当です(笑
				var n = chMx - i + 1;
				if(anime == "cards") {
					css[i] = {"elem":elem, "css":{"top":top,"left":left,"height":eH}};
					$(elem).css({"display":"block","top":0,"left":0,"width":eW,"height":eW,opacity:1,"z-index":n});
				} else if(anime == "fadein") {
					css[i] = {"elem":elem, "css":{opacity:1}};
					$(elem).css({"display":"block","top":top,"left":left,"width":eW,"height":eH,opacity:0});
				} else {
					// アニメーションさせる値を配列に格納(あとで一度に反映)
					css[i] = {"elem":elem, "css":{opacity:1,"height":eH}};
					// 初期CSS
					$(elem).css({"display":"block","top":top,"left":left,"width":eW,"height":0,opacity:0.5});
				}
				// 現在の横幅更新
				left += cW;
				//カウントアップ
				c++;
				if(c > clm) c = 0;
		});

		//縦幅が最も高いのカラムを求める
		//最初に1つ目のカラムだけ取得
		top = y[0];
		for(var q = 0;q < clm;q++) {
			if(y[q] > top) {
				top = y[q];
			}
		}
		// 親要素の高さを設定
		pr.height(top);

		// ランダムに呼び出してCSSを反映
		var i = css.length;
		var arr = new Array();
		var c = 0;
		var t = Math.floor(time / chMx);
		while(--i) {
			var j = Math.floor(Math.random() * (i + 1));
			arr[j] = j;
			if(css[j] != undefined) {
				delay = t * c;
				var e = css[j];
				$(e.elem).delay(delay).animate(e.css,{duration:240});
				css[j] = undefined;
				c++;
			}
		}
		// 残った要素にCSSを反映
		for (var i in css) {
			if(css[i] != undefined) {
				delay = t * c;
				var e = css[i];
				$(e.elem).delay(delay).animate(e.css,{duration:240});
				c++;
			}
		}
	}
};

動作デモ

記述ミスとか余計な部分があればご指摘頂ければ嬉しいです(ノД`)

後日追記:
“パネル風”と書いてましたが、よくよく考えてみたら”タイル状”ですね・・・。
変更しました(ノД`)

  • Pingback: トップページのデザインを変更しました | hlw.me

  • Kajiwara Teppei

    これすごいですね〜
    高さのことなるliを流し込む方法をずっと探してたのでめちゃくちゃ助かりました!

    • http://hlw.me/ hlw_me

      ありがとうございます!

      現在のトップページでは密かに変更を加えて、今はjQuery Masonryというライブラリを利用しております。
      こちらはオプションなども豊富で素晴らしいライブラリです。
      英語でとっつきにくいかもしれませんが、一度お試しくださいな!
      http://masonry.desandro.com/index.html