<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1650 1170" width="1650" height="1170" version="1.1" >
<!--
Johan Karlsson, 2020
https://twitter.com/DonKarlssonSan
-->
</svg>
body, html {
margin: 0;
background-color: #223;
cursor: pointer;
}
svg {
position: absolute;
width: 100%;
height: 100%;
}
/*
Johan Karlsson, 2020
https://twitter.com/DonKarlssonSan
MIT License, see Details View
*/
class Circle {
constructor(x, y) {
this.x = x;
this.y = y;
this.r = 10;
this.done = false;
}
draw(groupElement) {
this.drawCircle(groupElement, this.x, this.y, this.r * 0.92);
let d = mouseVector.sub(new Vector(this.x, this.y));
// Where's Waldo? 😉
let direction = Math.random() > 0.95 ? -1 : 1;
let p = d.div(d.getLength()).mult(this.r * 0.31 * direction);
this.drawCircle(groupElement, this.x + p.x, this.y + p.y, this.r * 0.6);
p.multTo(2);
this.drawCircle(groupElement, this.x + p.x, this.y + p.y, this.r * 0.3);
}
drawCircle(groupElement, x, y, r) {
let circle = createSvgElement("circle");
circle.setAttribute("cx", x);
circle.setAttribute("cy", y);
circle.setAttribute("r", r);
groupElement.appendChild(circle);
}
}
let svg;
let w = 1650;
let h = 1170;
let margin = 0.15;
let circles;
let mouseVector;
function setup() {
svg = document.querySelector("svg");
svg.addEventListener("mousemove", mousemove);
document.addEventListener("click", draw);
document.addEventListener("keydown", onKeyDown);
}
function onKeyDown (e) {
if(e.code === "KeyD") {
download();
}
}
function download() {
let svgDoc = svg.outerHTML;
let filename = `big-brother.svg`;
let element = document.createElement("a");
element.setAttribute("href", "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svgDoc));
element.setAttribute("download", filename);
element.style.display = "none";
document.body.appendChild(element);
element.addEventListener("click", e => e.stopPropagation());
element.click();
document.body.removeChild(element);
}
function dist(x1, y1, x2, y2) {
return Math.hypot(x1 - x2, y1 - y2);
}
function addCircles() {
let nrOfTries = 0;
let wasAdded;
do {
wasAdded = false;
let x = (1 - margin * 2) * Math.random() * w + w * margin;
let y = (1 - margin * 2) * Math.random() * h + h * margin;
if(validPos(x, y)) {
wasAdded = true;
let c = new Circle(x, y);
circles.push(c);
}
nrOfTries++;
} while (!wasAdded && nrOfTries < 50)
}
function validPos(x, y) {
for(let i = 0; i < circles.length; i++) {
let current = circles[i];
let d = dist(x, y, current.x, current.y);
if(d - 10 < current.r) {
return false;
}
}
return true;
}
function canGrow(circle) {
if(circle.x - circle.r < w * margin) return false;
if(circle.y + circle.r > h * (1 - margin)) return false;
for(let i = 0; i < circles.length; i++) {
let current = circles[i];
if(circle !== current) {
let d = dist(circle.x, circle.y, current.x, current.y);
if(d - 4 <= circle.r + current.r) {
return false;
}
}
}
return true;
}
function resetCircles() {
circles = [];
}
function packCircles() {
let nrOfTries = w * h / 400;
for(let i = 0; i < nrOfTries; i++) {
if(i % 2 === 0) {
addCircles();
}
circles.filter(c => !c.done).forEach(c => {
if(canGrow(c)) {
c.r += 2;
} else {
c.done = true;
}
});
}
}
function drawCircles(groupElement) {
circles.forEach(c => c.draw(groupElement));
}
function draw() {
console.clear();
mouseVector = new Vector((1 - margin * 2) * w * Math.random(), (1 - margin * 2) * h * Math.random());
let group = document.querySelector("#container");
if (group) {
group.remove();
}
group = createSvgElement("g");
group.setAttribute("id", "container");
group.setAttribute("fill", "none");
group.setAttribute("stroke", "white");
group.setAttribute("stroke-linecap", "round");
group.setAttribute("stroke-linejoin", "round");
resetCircles();
packCircles();
drawCircles(group);
let logo = new Logo(w * 0.89, h * 0.92, "white");
logo.draw(group);
svg.appendChild(group);
}
function mousemove(event) {
mouseVector.x = event.clientX;
mouseVector.y = event.clientY;
}
function createSvgElement(elementName) {
const svgNs = "http://www.w3.org/2000/svg";
return document.createElementNS(svgNs, elementName);
}
setup();
draw();
This Pen doesn't use any external CSS resources.