Hi abk,
To give you a bit more details, what you need to realize is that you basically have one pattern (the 8 columns gradient) that get repeated several times but at different positions and different sizes.
Based on this, and because we are lazy and want to save writing code, a good solution would be to write a function that draw one gradient at a specific position and size. All you would need to do later, is to call that function with the proper arguments and the function will handle all the math to display the gradient properly.
Now you can go from bottom up (meaning that drawing function up to your setup part) but maybe position and size are not the best arguments to give the function because the logic is different. Because of that the first thing I did was to write the main frame of the code, to help me figure out how I wanted everything to work. I got this:
let colNb = 8; // The number of columns to display per gradient
let rowNb = 4; // The number of rows of gradients to display
function setup() {
createCanvas(windowWidth, windowHeight);
background(0);
// Draw 4 rows of the gradient
for (let i = 0; i < rowNb; i++) {
drawRow(i);
}
}
As you can see I want my main code to be really simple. All I want to do is decide the cumber of row of gradients I want to draw and call a function drawRow()
that will figure out the size of the gradients for that row and the size they should have.
Simple enough, let’s code this:
// Draw one row of gradients
// lvl is the row nb (strating at 0 = fullscreen)
function drawRow(lvl) {
let patternNb = pow(2, lvl); // The number of gradients to display in the row
let w = width / patternNb; // The width of one gradient in that row
let h = height / patternNb; // The height of the gradients in that row
// Draw the actual gradients
for (let i = 0; i < patternNb; i++) {
drawGradient(w, h, i);
}
}
As you can see, the piece of code does exactly what I explained above: finding the number of gradients to draw on that row and their size. In addition of course I want to actually draw them so for each gradient I want to draw I’m calling the drawGradient()
function.
And as you can see, I’m not giving it the position and size like I was saying in the beginning but the size and the index of that gradient in the row (0 is the most left, then 1 is just right to this one and so on…)
// Draw one gradient given its size and index in the row
function drawGradient(w, h, idx) {
let colWidth = w / colNb; // The size of one bar
let gradStep = 255 / colNb; // The step for the gradient
for (let i = 0; i < colNb; i++) {
fill(255 - i * gradStep);
noStroke();
rect(idx * w + i * colWidth, height - h, colWidth, h);
}
}
And voilà!
You can change the number of columns per gradient as well as the number of row to display really easily with this.
EDIT:
To avoid gaps between rectangles, you can simply draw wider rectangles. The excess part will be drawn over by the next rectangle.
So instead of
rect(idx * w + i * colWidth, height - h, colWidth, h);
You have
rect(idx * w + i * colWidth, height - h, 1.5 * colWidth, h);