Imperfect Rectangles
to generate a new and unique variation
Every variart piece is open source, you can see exactly how it is drawn from the code.
// adapted from http://rectangleworld.com/blog/archives/443
var colors = [];
var displayWidth = width;
var displayHeight = height;
function setLinePoints(iterations) {
var pointList = {};
pointList.first = {x:0, y:1};
var lastPoint = {x:1, y:1}
var minY = 1;
var maxY = 1;
var point;
var nextPoint;
var dx, newX, newY;
var ratio;
var minRatio = 0.33;
pointList.first.next = lastPoint;
for (var i = 0; i < iterations; i++) {
point = pointList.first;
while (point.next != null) {
nextPoint = point.next;
ratio = minRatio + Math.random()*(1 - 2*minRatio);
newX = point.x + ratio*(nextPoint.x - point.x);
//find the smaller interval
if (ratio < 0.5) {
dx = newX - point.x;
}
else {
dx = nextPoint.x - newX;
}
newY = point.y + ratio*(nextPoint.y - point.y);
newY += dx*(Math.random()*2 - 1);
var newPoint = {x:newX, y:newY};
//min, max
if (newY < minY) {
minY = newY;
}
else if (newY > maxY) {
maxY = newY;
}
//put between points
newPoint.next = nextPoint;
point.next = newPoint;
point = nextPoint;
}
}
//normalize to values between 0 and 1
if (maxY != minY) {
var normalizeRate = 1/(maxY - minY);
point = pointList.first;
while (point != null) {
point.y = normalizeRate*(point.y - minY);
point = point.next;
}
}
//unlikely that max = min, but could happen if using zero iterations. In this case, set all points equal to 1.
else {
point = pointList.first;
while (point != null) {
point.y = 1;
point = point.next;
}
}
return pointList;
}
function generate() {
var x0, y0, w, h;
var lineColor;
var fillColor;
var minWidth = 80;
var maxWidth = 280;
var minHeight = minWidth;
var maxHeight = maxWidth;
var numRects = 6;
for (var i = 0; i < numRects; i++) {
r = Math.floor(Math.random()*255);
g = Math.floor(Math.random()*255);
b = Math.floor(Math.random()*255);
a = 0.9;
fillColor = "rgba("+r+","+g+","+b+","+a+")";
lineColor = "rgba("+r+","+g+","+b+","+a+")";
w = minWidth + Math.random()*(maxWidth - minWidth);
h = minHeight + Math.random()*(maxHeight - minHeight);
x0 = 6 + Math.random()*(displayWidth - w - 6);
y0 = 6 + Math.random()*(displayHeight - w - 6);
drawRect(x0, y0, w, h, lineColor, fillColor);
}
}
function drawRect(x0,y0,w,h,lineColor,fillColor) {
var cornerDrift = 3;
var drawDriftX = 3;
var drawDriftY = 3;
var corner = [];
var driftVector = [];
var pointList;
var i,j;
var nextCorner;
var iterates = 8;
var nextX, nextY;
var functionPoint;
var endpointY;
x0 += cornerDrift*(2*Math.random()-1);
y0 += cornerDrift*(2*Math.random()-1);
for (i = 0; i < 4; i++) {
corner[i] = {};
}
corner[0].x = x0 + cornerDrift*(Math.random()*2 - 1);
corner[0].y = y0 + cornerDrift*(Math.random()*2 - 1);
corner[1].x = x0 + w + cornerDrift*(Math.random()*2 - 1);
corner[1].y = y0 + cornerDrift*(Math.random()*2 - 1);
corner[2].x = x0 + w + cornerDrift*(Math.random()*2 - 1);
corner[2].y = y0 + h + cornerDrift*(Math.random()*2 - 1);
corner[3].x = x0 + cornerDrift*(Math.random()*2 - 1);
corner[3].y = y0 + h + cornerDrift*(Math.random()*2 - 1);
driftVector[0] = {x:0, y:drawDriftY};
driftVector[1] = {x:drawDriftX, y:0};
driftVector[2] = {x:0, y:drawDriftY};
driftVector[3] = {x:drawDriftX, y:0};
var points = [];
points.push(corner[0].x, corner[0].y);
for (i = 0; i < 4; i++) {
nextCorner = corner[(i + 1) % 4];
pointList = setLinePoints(iterates);
functionPoint = pointList.first;
endpointY = functionPoint.y;
while (functionPoint != null) {
nextX = corner[i].x + functionPoint.x*(nextCorner.x - corner[i].x);
nextY = corner[i].y + functionPoint.x*(nextCorner.y - corner[i].y);
nextX += driftVector[i].x*(functionPoint.y - endpointY);
nextY += driftVector[i].y*(functionPoint.y - endpointY);
console.log('lineTo', nextX, nextY);
points.push(nextX, nextY);
functionPoint = functionPoint.next;
}
}
s.polyline(points).attr({
fill: fillColor,
opacity: 0.2,
stroke: lineColor,
strokeWidth: 2
});
}
generate();
Copyright © 2014–2025 Kevin Marsh. All rights reserved. Questions? Comments? hello@variart.io