最近ツール紹介の記事が多かったので、少し頭の体操がてらロジックについて話したいと思います。
Pinterestに代表されるような可変レイアウトだったり、数が決められない(CMSからシステムアウトする)メニューやツールチップなど、一見複雑そうなレイアウトになると、
などと考えがちですが、実は簡単な算数で計算されていることも多いです。
今回は要素の折り返し最大数は決めたいけど、まとまってレイアウトされたいよね。っていうのを考えたいと思います。何を言っているかわからないでしょうが、w
例えば
「最大4つで折り返す」
というレイアウトを考えたとしても、1行目と2行目がアンバランスなのは格好悪いので
ということですね。
何に使うの?
という声も聞こえてきそうですが、
ボタンクリック後に出てくるツールチップメニューなどボタンを中心にまとまっていてほしいですし、
画面サイズ/カラムによって、レイアウトを組むときにも応用できるでしょうし、
動的に何かを制御するときの考え方としては入門編かなと思います。
何かと苦手な人の多い sin()、cos()、tan() などの三角関数なども出てきませんし、ビット演算なども出てきません。w
まず考えなければいけないのは、全体の数に対して横何行・縦何列の中に収まるかということです。
最大4列までとするなら、
頭の中では、
3だったら2と1に並べて2行2列、
6だったら3と3で2行3列、
9だったら4と4と1で3行4列
とすぐにでてくるのですが、なかなか計算で出そうと思うと悩むところだと思います。
ただこれさえ理解すればあとはいつものサムネイルを配置するときなどと同じ考え方で大丈夫かと思います。
とすると、列数COLUMN_NUMと、行数LINE_NUMはそれぞれJSで書くと
var COLUMN_NUM = Math.min(Math.ceil(OBJ_NUM * 0.5 ), MAX_COLUMN); var LINE_NUM = Math.ceil(OBJ_NUM / COLUMN_NUM);
となります。
解説すると、
となります。
あとは要素を順番に、配置していくだけです。
var i=0; var posX, posY; //ボタンを中心(0,0)として要素を配置した際の(x, y)=(posX, posY)とする。 for(; i < OBJ_NUM; i++){ posX = (i % COLUMN_NUM - COLUMN_NUM * 0.5) * OBJ_WIDTH; //OBJ_WIDTHは要素の横幅 posY = (Math.floor(i / COLUMN_NUM) - LINE_NUM * 0.5) * OBJ_HEIGHT; //OBJ_HEIGHTは要素の高さ }
少しだけ噛み砕くと、
X座標は、
全体の数を横に並べる数で割った余り(i % COLUMN_NUM)番目の列の位置から、
全体の半分の長さを引く(COLUMN_NUM * OBJ_WIDTH * 0.5)。
posX = i % COLUMN_NUM * OBJ_WIDTH - COLUMN_NUM * OBJ_WIDTH * 0.5;
となるので、それを整理すると、
posX = (i % COLUMN_NUM - COLUMN_NUM * 0.5) * OBJ_WIDTH;
Y座標は、
全体の数を横に並べる数で割った数(Math.floor(i / maxW))番目の行の位置から、全体の半分の高さ(LINE_NUM * OBJ_HEIGHT * 0.5)を引く
posX = Math.floor(i / COLUMN_NUM) * OBJ_HEIGHT - LINE_NUM * OBJ_HEIGHT * 0.5
となるので、同じく整理すると、
posY = (Math.floor(i / COLUMN_NUM) - LINE_NUM * 0.5) * OBJ_HEIGHT;
※全体の半分の長さ/高さを引くのは、全体を中心揃えにするため。
どうでしょうか。
今回は3行目の端数は無視してますが、同じような考え方で、9の場合は、上4つ中4つ下1つでなく、上も中も下も3つずつというレイアウトも可能になります。
頭の中では簡単にできることでも、それをロジック的に考えると色々と応用できますので、食わず嫌いせずに頭の体操がてら考えてみるのも一興かと思います。