circle packing
by michae1
HTML
<div class="field">
<div class="target"></div>
</div>
CSS
.field {
position: relative;
width: 300px;
height: 300px;
box-sizing: border-box;
border: 1px solid #dbdbdb;
background-color: white;
overflow: auto;
}
.target {
position: absolute;
top: 50%;
left: 50%;
}
.avatar {
position: absolute;
border-radius: 50%;
border: 1px solid;
overflow: hidden;
box-sizing: border-box;
padding: 10px;
text-align: center;
transition: all .2s ease-out;
}
.avatar:hover {
background-color: #dbdbdb;
width: 80px !important;
height: 80px !important;
z-index: 2;
box-shadow: 2px 2px 2px rgba(0,0,0,.3);
}
JavaScript
var target = document.querySelector('.target');
var circles = [];
function addCircle(radius) {
radius = radius || Math.floor(Math.random() * 5 + 20);
var coordss = findPosition(radius);
circles.push({
coords: {
x: coordss.x,
y: coordss.y
},
radius: radius
});
var avatar = document.createElement('div');
avatar.style.width = radius * 2 + 'px';
avatar.style.height = radius * 2 + 'px';
avatar.style.top = coordss.y - radius + 'px';
avatar.style.left = coordss.x - radius + 'px';
avatar.className = 'avatar';
avatar.innerHTML = circles.length;
target.appendChild(avatar);
}
function isCollision (newCircle) {
var currentCircle;
var deltaX;
var deltaY;
var distance;
for (var i = 0, len = circles.length; i < len; i ++) {
currentCircle = circles[i];
deltaX = newCircle.coords.x - currentCircle.coords.x;
deltaY = newCircle.coords.y - currentCircle.coords.y;
distance = Math.sqrt(deltaX*deltaX + deltaY*deltaY)
if (distance < newCircle.radius + currentCircle.radius) {
return true;
}
}
return false;
}
function findPosition (radius) {
var minDistance;
var deltaAngle = 1;
var distance = 0;
var x, y;
for (var angle = 0; angle < 360; angle += deltaAngle) {
distance = 0
x = Math.cos(angle) * distance;
y = Math.sin(angle) * distance;
while (isCollision({
coords: {
x: x,
y: y
},
radius: radius
})) {
distance++;
x = Math.cos(angle) * distance;
y = Math.sin(angle) * distance;
};
if (angle === 0 || distance < minDistance.distance) {
minDistance = {
distance: distance,
coords: {
x: x,
y: y
}
}
}
}
return {
x: minDistance.coords.x,
y: minDistance.coords.y
}
}
function init () {
addCircle(10);
for (var i = 0; i < 7; i++) {
addCircle();
}
}
init();