我正在尝试制作一些东西,其中一堆圆圈(带有border-radius的div)可以动态生成并放置在它们的容器中而不会重叠。
这是我目前的进展 - https://jsbin.com/domogivuse/2/edit?html,css,js,output
var sizes = [200, 120, 500, 80, 145];
var max = sizes.reduce(function(a, b) {
return Math.max(a, b);
});
var min = sizes.reduce(function(a, b) {
return Math.min(a, b);
});
var percentages = sizes.map(function(x) {
return ((x - min) * 100) / (max - min);
});
percentages.sort(function(a, b) {
return b-a;
})
var container = document.getElementById('container');
var width = container.clientWidth;
var height = container.clientHeight;
var area = width * height;
var maxCircleArea = (area / sizes.length);
var pi = Math.PI;
var maxRadius = Math.sqrt(maxCircleArea / pi);
var minRadius = maxRadius * 0.50;
var range = maxRadius - minRadius;
var radii = percentages.map(function(x) {
return ((x / 100) * range) + minRadius;
});
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
var coords = [];
radii.forEach(function(e, i) {
var circle = document.createElement('div');
var randomTop = getRandomArbitrary(0, height);
var randomLeft = getRandomArbitrary(0, width);
var top = randomTop + (e * 2) < height ?
randomTop :
randomTop - (e * 2) >= 0 ?
randomTop - (e * 2) :
randomTop - e;
var left = randomLeft + (e * 2) < width ?
randomLeft :
randomLeft - (e * 2) >= 0 ?
randomLeft - (e * 2) :
randomLeft - e;
var x = left + e;
var y = top + e;
coords.push({x: x, y: y, radius: e});
circle.className = 'bubble';
circle.style.width = e * 2 + 'px';
circle.style.height = e * 2 + 'px';
circle.style.top = top + 'px';
circle.style.left = left + 'px';
circle.innerText = i
container.appendChild(circle);
});
我已将它们添加到父容器中,但您可以看到它们重叠,我真的不知道如何解决这个问题。我尝试实现像(x1 - x2)^2 + (y1 - y2)^2 < (radius1 + radius2)^2
这样的公式,但我不知道这个。
任何帮助表示感谢。
答案 0 :(得分:1)
你要做的事情被称为“包装”,实际上是一个非常难的问题。您可以在这里采取几种可能的方法。
首先,您可以随机分发它们(就像您目前正在做的那样),但包括“重试”测试,如果圆圈与另一个圆圈重叠,您可以尝试新的位置。由于可能最终处于不可能的情况,您还需要一个重试限制,此时它会放弃,返回到开头,并尝试再次随机放置它们。这种方法相对容易,但是由于重叠的可能性非常高,因此无法将它们打包得非常密集。如果圆圈覆盖了总面积的1/3,这可能会有效。
其次,您可以在添加更多时调整先前放置的圆圈的位置。这更像是在物理上如何完成 - 当你添加更多时,你开始不得不推开附近的那些以便适应新的。这不仅需要找到当前圆圈所击中的东西,还需要找到那些要移动的东西。我建议类似于“弹性”算法的东西,你随机放置所有圆圈(不考虑它们是否合适),然后有一个循环,你计算重叠,然后根据重叠在每个圆圈上施加一个力(他们互相推开)。这将使圆圈彼此远离,直到它们停止重叠。它还将支持一个圆圈将第二个圆圈推入第三个圆圈,依此类推。这将是更复杂的编写,但将支持更密集的配置(因为它们最终可能最终触摸)。你仍然可能需要一个“这是不可能的”检查,以防止它被卡住并永远循环。