グリッドデザイン的なものをjQueryでしようかと思っていたのですが、ちょうどいいのが見つからなかったので自作してみました。
今回の場合、グリッドの大枠の横幅は制限があり、縦に伸びる形です。また、グリッドの各マスは正方形で、入れるボックスはマスの倍数の大きさになります。たとえば、2マス×3マスのようにボックスは縦横が任意の大きさにすることができます。大きさはボックスのHTMLクラスによって指定し、jQueryで指定した大きさに変更する形です。
クラスによって大きさを指定させたのは自分でボックスごとに指定したかったためなのですが、内容物に合わせて大きさを変更するにはもうちょっとカスタマイズが必要です。
HTML
ここではHTMLの記述をします。HTMLはシンプルな構成になっており、外枠となる「#GridLayout」の直下に、ボックスとなる「div」を入れていくだけです。「GridBox」の後の数字が何マス分の大きさかを表し、「GridBox_横_縦」で指定ができます。注意点としては、ボックスを左上から空いているところへ順に埋めていく形になるため、大きいのばかりでは空白ができてしまいます。そのため、1×1のボックスもある程度必要になります。また、のちにjQueryで指定する列の最大数を超える横幅を指定してしまった場合、空いてるマスのチェックが終わらずブラウザが応答しなくなるかもしれません。
1 2 3 4 5 6 7 8 9 10 |
<div id="GridLayout"> <div class="GridBox_1_2">内容1</div> <div class="GridBox_2_2">内容2</div> <div class="GridBox_3_2">内容3</div> <div class="GridBox_3_2">内容4</div> <div class="GridBox_1_5">内容5</div> ・ ・ ・ </div> |
CSS
必要なCSSはもっと単純です。外枠の横幅指定とデザインについては、サイトのサイズに合わせてご変更ください。1マスの縦横の長さは、後ほどjQueryで指定します。
この例だと、横960pxの外枠に1マス160pxのマスが横に6つ入る形になっています。
1 2 3 4 5 6 7 |
#GridLayout { width:960px; position:relative;} #GridLayout > div{ position:absolute; top:0; left:0;} |
jQuery
jQueryの部分は継ぎ足し継ぎ足しで作成したため、いらない部分があるかもしれませんし複雑かもしれませんが、変更するのは「1マスの1辺の長さ(GridW)」と「ボックスのマージン(Margin)」、「列の最大数(ColMax)」の3つだけです。
後で細かく説明していきますが、基本的な流れとしては、ボックスに対しクラスから大きさを読み取り、ボックスが入るマスがあれば順々に埋めていく形です。ボックスがすでに入っているかどうかは配列に情報を格納しています。最後に外枠の高さを変更しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
$(function(){ var GridW = 160,//---------------------1マスの1辺の長さ Margin = 5,//----------------------ボックスのマージン ColMax = 6,//----------------------列の最大数 GridTable = [], RowMax = 0; $('#GridLayout > div').each(function(i){ SpaceChk = 'No'; WH = $(this).attr('class').split('_'); W = parseInt(WH[1]); H = parseInt(WH[2]); Col = 0; Row = 0; while ( SpaceChk == 'No') { TableID = Col+'-'+Row; AreaChk = 'Yes'; for(a=0; a < W; a++){ ColA = Col+a; for(b=0; b < H; b++){ RowB = Row+b; if(jQuery.inArray(ColA+'-'+RowB,GridTable) != -1){AreaChk = 'No';} } } if(AreaChk == 'Yes' && Col+W < ColMax+1){ for(a=0; a < W; a++){ ColA = Col+a; for(b=0; b < H; b++){ RowB = Row+b; GridTable.push(ColA+'-'+RowB); $(this).append('<br>'+ColA+'-'+RowB); if(RowB > RowMax) { RowMax=RowB; } } } Left = Col*GridW; Top = Row*GridW; $(this).animate({ 'left':Left+'px', 'top':Top+'px', 'width':(GridW*W)-(Margin*2)+'px', 'height':GridW*H-(Margin*2)+'px' }); SpaceChk = 'Yes'; } if(Col == ColMax ){ Col = 0; Row++; }else{ Col++; } } }); $('#GridLayout').animate({'height':(RowMax+1)*GridW}); }); |
ボックスに対しての処理
1 2 3 |
$('#GridLayout > div').each(function(i){ } |
このコードではそれぞれのボックスに対しての処理がを行います。外枠のIDを変更している場合や直下に別のdivタグは入っている場合は変更してください。
初期化とクラスの読み取り
1 2 3 4 5 6 |
SpaceChk = 'No'; WH = $(this).attr('class').split('_'); W = parseInt(WH[1]); H = parseInt(WH[2]); Col = 0; Row = 0; |
ここではボックスごとに初期化を行っています。SpaceChkはボックスを埋める際、空いているかどうかの変数です。
attrでクラスを取得したあと、splitを利用し「_」で分割して「WH」に配列として格納しています。そのため、HTMLでは「grid-1-1」のように他の区切り文字にした場合は、「split(‘-‘)」のように変更します。
splitを利用して複数の情報を読み取ることについては、別にこちらの記事で書いています。
横と縦がそれぞれ何マスに指定したかは、parseIntで整数に直し、WとHに格納しています。
ColとRowは、マスのチェックの際に指標として利用します。
空いている箇所が見つかるまでマスを検索
1 2 3 4 5 6 7 8 9 10 11 |
while ( SpaceChk == 'No') { TableID = Col+'-'+Row; AreaChk = 'Yes'; //中略 if(Col == ColMax ){ Col = 0; Row++; }else{ Col++; } } |
while文によって、ボックスが入るだけのマスが見つかるまで、マスを検索していきます。
TableIDは今どこのマスをチェックしているかの指標です。
AreaChk = ‘Yes’;は空いてるマスが見つかった後、横幅と縦幅分入るかどうかのチェック用になります。この辺をもう少し省略して書ければいいのですが。。。
最後のif分岐は、マスを左から列数が最大数になるまで順にみていき、空いていなかったらその次の行へ移る形です。
マスが入るかのチェック
1 2 3 4 5 6 7 8 9 10 11 |
for(a=0; a < W; a++){ ColA = Col+a; for(b=0; b < H; b++){ RowB = Row+b; if(jQuery.inArray(ColA+'-'+RowB,GridTable) != -1){AreaChk = 'No';} } } if(AreaChk == 'Yes' && Col+W < ColMax+1){ //中略 SpaceChk = 'Yes'; } |
for分を使い、空いてるマスに対して横幅が入るか、縦幅が入るかをチェックするため、隣のマスや下のマスを調べていきます。
jQuery.inArray(ColA+'-'+RowB,GridTable) != -1
は、配列(GridTable)の中に現在の指標(ColA+’-‘+RowB)が存在するかをチェックしています。
inArrayは、配列に存在しない場合に-1を返すため、もしマスが空いている場合は-1を返すことになります。
この場合では逆に、マスにボックスがあった場合に「AreaChk = ‘No’」を設定することで、次のif文、if(AreaChk == 'Yes' && Col+W < ColMax+1)
を通り過ぎる設定になります。
if文を通るとSpaceChk = ‘Yes’;となり前の項目のwhile文を抜け、通り過ぎると次の列や行をチェックします。
GridTableには、if文の中の記述によりボックスが埋まっている指標が格納されているため、現在のチェックしている指標(ColA+’-‘+RowB)が埋まっているかどうかが分かります。
もう一つある条件式Col+W < ColMax+1
では、ボックスが外枠からはみ出るのを防ぐために足しています。そのため、もし最大数を超える横の大きさを設定してしまった場合は、チェックが永遠に終わることはないので止まってしまう可能性があるかもしれません。
マスの埋まっている情報を配列に格納
1 2 3 4 5 6 7 8 9 |
for(a=0; a < W; a++){ ColA = Col+a; for(b=0; b < H; b++){ RowB = Row+b; GridTable.push(ColA+'-'+RowB); $(this).append('<br>'+ColA+'-'+RowB); if(RowB > RowMax) { RowMax=RowB; } } } |
もし、指標に対して横幅と縦幅が入る分だけマスが空いていた場合の処理になります。
ここではボックスが利用したマスが他と被らないように、配列「GridTable」に利用するマスの指標を格納しておきます。
.push(ColA+’-‘+RowB)で配列「GridTable」に追加しています。
また、 if(RowB > RowMax) { RowMax=RowB; }
では、最大行を図るため、RowMaxを更新していく仕組みです。
ボックスの移動
1 2 3 4 5 6 7 8 |
Left = Col*GridW; Top = Row*GridW; $(this).animate({ 'left':Left+'px', 'top':Top+'px', 'width':(GridW*W)-(Margin*2)+'px', 'height':GridW*H-(Margin*2)+'px' }); |
ここでは実際にボックスを動かしています。また、ボックスの大きさもここで指定しているため、もし重い場合はしばらく表示されないということも考えられます。そのため、別の個所で大きさを変更するよう設定してもいいかもしれません。
外枠の高さを修正
1 |
$('#GridLayout').animate({'height':(RowMax+1)*GridW}); |
外枠やボックスのスタイルをCSSでrelativeとabsoluteにしているため、このままでは外枠に高さがありません。そのため、最後に行の分だけ外枠の高さを更新しています。
これにより、外枠の高さが可変となります。
まとめ
自作したグリッドデザインの方法は以上になります。今後右上から動くのではなくランダムな位置から集まったりなどのカスタマイズをするかもしれませんが、自作すればどこを変更したらいいかわかるので、案外その後が楽だったりします。
コメントを残す