Skip to content

Instantly share code, notes, and snippets.

@Gazzell
Created December 12, 2018 22:13
Show Gist options
  • Save Gazzell/5fe8e55e97e91a40c08e09092e816bae to your computer and use it in GitHub Desktop.
Save Gazzell/5fe8e55e97e91a40c08e09092e816bae to your computer and use it in GitHub Desktop.
circles
<canvas id='canvas' width='800' height='800'></canvas>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
const maxRadius = 50;
const minRadius = 3;
const cellSize = maxRadius * 2;
const cellsX = Math.ceil(width / cellSize);
const cellsY = Math.ceil(height / cellSize);
const circleCells = [];
for(let i = 0; i < width * height; i++) {
circleCells.push([]);
}
function getCell(x, y) {
const cellX = Math.floor(x / cellSize);
const cellY = Math.floor(y / cellSize);
return cellX + cellY * cellsX;
}
function getAdjacentCells(x, y) {
let cells = [];
function tryPushCell(cellToPush) {
if (cellToPush >= 0 && cellToPush <= circleCells.length) {
circleCells[cellToPush].forEach(circle => cells.push(circle));
}
}
const cell = getCell(x, y);
tryPushCell(cell);
tryPushCell(cell - cellsX);
tryPushCell(cell + cellsX);
if(x > cellSize) {
tryPushCell(cell - 1);
tryPushCell(cell - 1 - cellsX);
tryPushCell(cell - 1 + cellsX);
}
if(x < width - cellSize) {
tryPushCell(cell + 1);
tryPushCell(cell + 1 - cellsX);
tryPushCell(cell + 1 + cellsX);
}
return cells;
}
function getRandomPos() {
return { x: Math.random() * width, y: Math.random() * height };
}
function drawCircle(x, y, radius) {
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.stroke();
}
function drawLine(x, y, x2, y2) {
ctx.strokeStyle = 'lime';
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function distance(x1, y1, x2, y2) {
const x = x2 - x1;
const y = y2 - y1;
return Math.sqrt(x * x + y * y);
}
function getClosestCircle(x, y) {
const cells = getAdjacentCells(x, y);
return cells.reduce((acc, circle) => {
if (!acc) {
return circle;
}
return distance(x, y, circle.x, circle.y) - circle.radius < distance(x, y, acc.x, acc.y) - acc.radius? circle : acc;
}, null);
}
function draw () {
const pos = getRandomPos();
const closest = getClosestCircle(pos.x, pos.y);
let radius = maxRadius;
if(closest) {
const dist = distance(pos.x, pos.y, closest.x, closest.y);
radius = dist < closest.radius + maxRadius ? dist - closest.radius : maxRadius;
}
if(radius > minRadius) {
drawCircle(pos.x, pos.y, radius);
if (closest) {
drawLine(pos.x, pos.y, closest.x, closest.y);
}
circleCells[getCell(pos.x, pos.y)].push({ x: pos.x, y:pos.y , radius });
}
requestAnimationFrame(draw);
}
draw();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment