Vibacious
to generate a new and unique variation
Every variart piece is a small program. This is the one that drew what you're looking at.
var bundles = intVariable('bundles', 1, 3);
var lineCount = intVariable('lines', 8, 16);
var dotSpacing = intVariable('dotSpacing', 12, 28);
var gold = '#EFB733';
var magenta = '#C12A7C';
var purple = '#5E3582';
var shade = '#6B2C74';
var silver = '#A7A2A8';
var margin = 60;
// Enough overdraw that the rotated ground still covers every corner
var bleed = 110;
var background = s.group();
background.add(s.rect(-bleed, -bleed, width + bleed * 2, height + bleed * 2).attr({fill: s.gradient('L(0, 0, ' + width + ', ' + height + ')' + gold + '-' + magenta + ':40-' + purple)}));
var rotation = getRandomArbitary(0, 360);
var cos = Math.cos(rotation * Math.PI / 180);
var sin = Math.sin(rotation * Math.PI / 180);
function onCanvas(x, y, r) {
var px = (x - width / 2) * cos - (y - height / 2) * sin + width / 2;
var py = (x - width / 2) * sin + (y - height / 2) * cos + height / 2;
return px > -r && px < width + r && py > -r && py < height + r;
}
// Halftone on a 45 degree lattice, like the screen on a printed can. Each layer
// is one path of circles: thousands of separate elements hang the browser.
function halftone(spacing, color, radiusAt) {
var d = [];
var firstRow = Math.floor(-bleed * 2 / spacing);
for (var row = firstRow; row * spacing / 2 < height + bleed; row++) {
var shift = row % 2 === 0 ? 0 : spacing / 2;
for (var x = shift - bleed - spacing; x < width + bleed; x += spacing) {
var y = row * spacing / 2;
var r = radiusAt(x, y);
if (r > 0.3 && onCanvas(x, y, r)) {
d.push('M' + (x - r).toFixed(1) + ',' + y.toFixed(1) +
'a' + r.toFixed(2) + ',' + r.toFixed(2) + ' 0 1,0 ' + (r * 2).toFixed(2) + ',0' +
'a' + r.toFixed(2) + ',' + r.toFixed(2) + ' 0 1,0 ' + (-r * 2).toFixed(2) + ',0');
}
}
}
background.add(s.path(d.join('')).attr({fill: color}));
}
var diagonal = width * Math.SQRT2;
var goldReach = getRandomArbitary(0.35, 0.55);
// Radii scale with the lattice, so the screen zooms without changing its density
var dotScale = dotSpacing / 9;
halftone(dotSpacing, shade, function(x, y) {
return dotScale * (1.2 + 2.2 * (x + y) / (width + height));
});
halftone(dotSpacing, gold, function(x, y) {
var fade = 1 - Math.sqrt(x * x + y * y) / (diagonal * goldReach);
return dotScale * 4.2 * fade;
});
background.transform('r' + rotation + ',' + width / 2 + ',' + height / 2);
function wavyBundle(centerX, maxSpread) {
var frequency = getRandomArbitary(0.8, 1.6);
var phase = getRandomArbitary(0, Math.PI * 2);
// Every line in a bundle shares one wobble, so they ripple together
var wobblePhase = getRandomArbitary(0, Math.PI * 2);
var wobbleSize = getRandomArbitary(4, 12);
for (var i = 0; i < lineCount; i++) {
var offset = i / (lineCount - 1) - 0.5;
var path = '';
for (var y = -10; y <= height + 10; y += 5) {
var pinch = 0.72 + 0.28 * Math.sin(y / height * Math.PI * 2 * frequency + phase);
var wobble = wobbleSize * Math.sin(y / height * Math.PI * 3 + wobblePhase);
var x = centerX + offset * maxSpread * pinch + wobble;
path += (path === '' ? 'M' : 'L') + x.toFixed(1) + ',' + y;
}
s.path(path).attr({fill: 'none', stroke: silver, strokeWidth: 2.5});
}
}
var slot = (width - margin * 2) / bundles;
for (var b = 0; b < bundles; b++) {
wavyBundle(margin + slot * (b + 0.5), slot * 0.8);
}
Copyright © 2014–2026 Logic and Matter. All rights reserved. Questions? Comments? hello@variart.io