これも後を引きずる問題?
absoluteで重なるとき右に避けて表示したい
http://oshiete.goo.ne.jp/qa/7968322.html
おそらく、定形の大きさのタイルを重ならないようにランダム配置したいのだと思う。
なので、与えられた2つの四角形(座標)が重なるか?を調べる関数を書く。
もしくは、並べる要素の style.margin-top をランダムにして float=left で並べる。
もしくは、最初の配置から座標が判っているのだから、四角形の四方の座標をストックする
追加したい四角形の4点が1つでもストックされた四角形の中ならアウト。
もしくは、この間のハート型の canvas のようにする。
上の問題を書いてみる。四角形がいびつだと重なる。検査点をもっと細かく区切ると反して遅くなる
しかしである、単純に考えて、空きスペースを探す総当たり検索と変わらない?!そう思う今。
というか、早く気づけ!>俺
<!DOCTYPE html> <meta charset="UTF-8"> <title></title> <style> ul { list-style: none; position:relative; } li { position: absolute; margin : 0; padding: 0; border: 1px red solid; text-align :center; font-size: 10px; color: red; width : 60px; height: 80px; } </style> <body> <h1>Position Test</h1> <ul> <li style="width: 50px; height:130px;">ABC <li style="width: 40px; height:80px;">DEF <li style="width: 100px; height:140px;">GHI <li style="width: 60px; height:70px;">JKL <li style="width: 150px; height:50px;">MNO <li style="width: 70px; height:30px;">PQR </ul> <script> (function () { // 四角形のオブジェクト function Square (element, top, left, right, bottom) { this.type = 'square'; this.element = element.tagName ? element: null; this.top = top; this.left = left; this.right = right; this.bottom = bottom; } // 引数(point) が四角形の内側にあるか? function isOverlap (point) { var x = point.x; var y = point.y; if (this.top <= y) if (y <= this.bottom) if (this.left <= x) if (x <= this.right) return true; return false; } // 位置を指定する function setPosition (position) { var d; if ((d = position.x)) { this.right = d + (this.right - this.left); this.left = d; } if ((d = position.y)) { this.bottom = d + (this.bottom - this.top); this.top = d; } } // 四角形のオブジェクトの生成 Square_create = function (e, x, y) { if (1 > arguments.length) throw new Error; x = x || 0, y = y || 0; return new Square (e, y, x, x + e.offsetWidth, y + e.offsetHeight); }; //______ Square.prototype.isOverlap = isOverlap; Square.prototype.setPosition = setPosition; Square.create = Square_create; this.Square = Square; //______ // エリアにすでに領域があるかを調べるモノ。 function AreaChecker () { this.stock = []; } // エリアに領域を加える function AreaChecker_add (area) { var e, s; if (! area) throw new Error (); if ((e = area.element)) { s = e.style; s.top = area.top + 'px'; s.left = area.left + 'px'; } this.stock.push (area); //配列に足すだけ }; // 点(this)が、与えられたエリアに含まれているのか? function overlap (area) { return this.some (area.isOverlap, area); } // 引数の領域が、エリアの領域とカブっているか? function getOverlap (area) { var points = [ ]; //検査する点 var result; var round = Math.round; if (! area) throw new Error (); if (! this.stock.length) return null; switch (area.type) { case 'square' : default : var st = 6; var sx = (area.right - area.left) / st; var sy = (area.bottom - area.top) / st; var left = area.left; var top = area.top; var i, j, t; for (i = 0; i <= st; i++) { t = round (sx * i); for (j = 0; j <= st; j++) { points.push ({ x: left + t, y: top + round (sy * j) }); } } break; } result = this.stock.filter (overlap, points); // 重なっているものを配列で返す return result.length ? result: null; } //__________________ function AreaChecker_create () { return new AreaChecker; } AreaChecker.prototype.add = AreaChecker_add; AreaChecker.prototype.getOverlap = getOverlap; AreaChecker.create = AreaChecker_create; this.AreaChecker = AreaChecker; }) (); //------------ var randomInt = function (n) { return Math.random () * n |0; }; var A = AreaChecker.create (); var li = document.querySelectorAll ('li'); // 面積順にする li = Array.prototype.slice.call (li, 0); // 配列化 function area (x, y) { return x * y }; // 面積をもとめる function comp (a, b) { var areaA = area(a.offsetWidth, a.offsetHeight); var areaB = area(b.offsetWidth, b.offsetHeight); return areaA == areaB ? 0: areaB - areaA; } li.sort (comp); (function () { var maxX = 240; var maxY = 120; var i = 0, j = 0; var e; var sq; var db; while (e = li[i++]) { sq = Square.create (e); j = 0; do { sq.setPosition ({x:randomInt (maxX), y:randomInt (maxY)}); db = A.getOverlap (sq); if (db) { sq.setPosition ({x: db[0].right + 1}); db = A.getOverlap (sq); if (++j > 20) throw new Error; } } while (db); A.add (sq); } }) (); </script>