Chroma Field
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.
// Vertical stripes, then triangles laid over them: inside a triangle the same
// stripes carry on but change colour, so the shape is read entirely in colour.
var backgroundColor = '#f2f0eb';
var colors = ['#ec3f8e', '#111111', '#2aa8c4', '#1c3fbf', '#f26722',
'#8dc63f', '#f5c518', '#e8412c', '#6a4fbf', '#1f7a3f'];
var stripes = intVariable("Stripes", 9, 22);
var triangles = intVariable("Triangles", 1, 3);
var barWidth = intVariable("Bar Width", 35, 80);
var margin = 60;
var span = width - margin * 2;
var pitch = span / stripes;
var bar = pitch * (barWidth / 100);
s.rect(0, 0, width, height).attr({fill: backgroundColor});
// One run of bars, coloured by the given picker, as its own group.
function stripeRun(pick){
var group = s.g();
for (var i = 0; i < stripes; i++){
var x = margin + i * pitch + (pitch - bar) / 2;
group.add(s.rect(x, margin, bar, height - margin * 2).attr({fill: pick(i)}));
}
return group;
}
// Never the same colour as the bar to its left, so every edge reads.
function runningPicker(){
var last = -1;
return function(){
var next = last;
while (next == last){
next = getRandomInt(0, colors.length - 1);
}
last = next;
return colors[next];
};
}
// A point somewhere along one side of the stripe field.
function edgePoint(side){
var near = margin;
var far = width - margin;
if (side == 0) return [getRandomInt(near, far), near];
if (side == 1) return [far, getRandomInt(near, far)];
if (side == 2) return [getRandomInt(near, far), far];
return [near, getRandomInt(near, far)];
}
function area(pts){
return Math.abs((pts[2] - pts[0]) * (pts[5] - pts[1]) -
(pts[4] - pts[0]) * (pts[3] - pts[1])) / 2;
}
stripeRun(runningPicker());
// Each triangle takes a corner from three neighbouring sides of the field. Three
// corners can still crowd into one corner of it, so anything under a fifth of
// the field is thrown back: a sliver reads as a mistake rather than a shape.
for (var t = 0; t < triangles; t++){
var smallest = span * span * 0.2;
var points;
for (var attempt = 0; attempt < 20; attempt++){
var first = getRandomInt(0, 3);
points = [];
for (var p = 0; p < 3; p++){
points = points.concat(edgePoint((first + p) % 4));
}
if (area(points) >= smallest) break;
}
var mask = s.g(s.polygon(points).attr({fill: '#ffffff'}));
stripeRun(runningPicker()).attr({mask: mask});
}
Copyright © 2014–2026 Logic and Matter. All rights reserved. Questions? Comments? hello@variart.io