我正在尝试制作一些可以动态生成一堆圆(具有边界半径的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
的公式,但是对此我一无所知。任何帮助表示赞赏。
最佳答案
您尝试做的事情叫做“包装”,实际上是一个非常棘手的问题。您可以在此处采取几种潜在的方法。
首先,您可以随机分配它们(就像您当前正在做的那样),但是要进行“重试”测试,在该测试中,如果一个圆与另一个圆重叠,则可以尝试一个新的位置。由于可能会在不可能的情况下结束,因此您还需要重试限制,在该限制下,它会放弃,回到起点,然后尝试再次随机放置它们。这种方法相对容易,但是缺点是您不能非常密集地打包它们,因为重叠的机会非常高。如果总面积的1/3可能被圆圈覆盖,则可能会起作用。
其次,您可以在添加更多圆时调整先前放置的圆的位置。这更等同于物理上的实现方式-随着添加的数量增加,您开始不得不推开附近的障碍物以适应新的障碍物。这不仅需要找到您当前圈子碰到的东西,而且还需要找到要移动该圈子的东西。我建议使用类似于“弹性”算法的方法,在该算法中,您将所有圆随机放置(不考虑它们是否适合),然后有一个循环来计算重叠,然后根据该重叠在每个圆上施加力(他们互相推开)。这将使圆彼此远离,直到它们不再重叠。它还将支持一个圆圈将第二个圆圈推入第三个圆圈,依此类推。这将编写起来更加复杂,但是将支持更密集的配置(因为它们最终可能最终接触到)。不过,您仍然可能需要进行“这是不可能的”检查,以防止其卡住并永远循环。