Hello and welcome to our community! Is this your first visit?
Enjoy an ad free experience by logging in. Not a member yet? Register.

# Thread: Math.random and fillRect with HTML5 Canvas

1. ## Math.random and fillRect with HTML5 Canvas

Hello, I'm new here so.. hi! You'll probably be seeing me a lot. Anyways here's my questions.

I am trying to get a function to draw 5 randomly sized and colored rectangles nested within each other. Meaning each rectangle should not go outside the boundaries of the rectangle it is in. The color thing I've got down in a `randomColor()` function. It's the nesting rectangles inside rectangles that is confusing me (hense me being up for the past 4 hours trying to understand it) I started out with very simple code just making 5 rectangles of reducing sizes nested in each other, then added the Math.random to randomize all the sizes. Now I'm at this point and have lost my way. Please help, or maybe there is just an easier way. I added a bunch of comments in my code so maybe you'll understand what I'm trying to do.

Code:
```function rect() { // rectangle generator
autoctx.clearRect(0, 0, 400, 400); // clear canvas
// declare variables
var x;
var y;
var width;
var height;
var i = 0; // counter

// create random x,y coordinates
x = Math.round(Math.random() * 100);
y = Math.round(Math.random() * 100);

do { // create random size rectangle
width = Math.round(Math.random() * 400);
height = Math.round(Math.random() * 400);
} while (width < 100 || height < 100); // make sure rectangle is big enough

autoctx.fillStyle = randomColor(); // Runs random color generator
autoctx.fillRect(x, y, width, height); // fill first rectangle

do {
x += (Math.round(Math.random() * 15)); // choose new random coordinates within previous rectangle
y += (Math.round(Math.random() * 15)); // choose new random coordinates within previous rectangle

//*********** KEEPS RECTANGLE HEIGHT AND WIDTHS FROM BEING A NEGATIVE NUMBER ***********//

do { //*** WIDTH TESTER ***// validates width to be within previous rectangles width
var testW = 0; // new width tester variable
testW = width - (Math.round(Math.random() * (2 * x))); // store test width
if (testW > 0) {
width = testW; // if test width > 0 store in width
}
} while (testW < 0); // if test width < 0 continue loop

do { //*** HEIGHT TESTER ***// validates height to be within previous rectangles height
var testH = 0; // create height testing variable
testH = height - (Math.round(Math.random() * (2 * y))); // calculate new test height
if (testH > 0) { // if test height is > 0
height = testH; // store as height
}
} while (testH < 0); // if test height < 0 try again

//*** Fills final rectangle values ***//
autoctx.fillStyle = randomColor(); // Runs random color generator
autoctx.fillRect(x, y, width, height);

i++; // add 1 to counter
} while (i < 4); // kick out of loop after the 5th rectangle
}```
thanks guys I hope I'm not too confusing or anything, any help would be greatly appreciated!

• In my opinion this should be rather a problem of analyzing and timing your operations. It has nothing to do with HTML5. It's just a logical sequence.

You have to focus on creating sets of (x,y,width,height) for all the 5 rectangles, following 2 simple rules:

After you create, randomly, the first set, try (in a loop) the new random set till:
1. the x in the new set is grater than the x from the first set. Same for the y.
2. the width in the new set is smaller than the width from the first set. same for the height.

Now repeat the operation. Except that the x,y,width and height value for comparison will be now the values from the previous created set.

All these should be don within a separate function which, in the end, should return an array (or an object), like:

Code:
```[
[x1,y1,w1,h1],
[x2,y2,w2,h2],
[x3,y3,w3,h3],
[x4,y4,w4,h4],
[x5,y5,w5,h5]
]```
Only now you should start the loop for fillStyle() and fillRect()

Need an example?

• Here's a quick example (untested):
Code:
```function returnSets(X,Y,W,H){
var minX=X,minY=Y,maxW=W,maxH=H;
var arr=[], x,y,w,h;
for(var i=0;i<5;i++){
x=Math.floor((W-minX+1)*Math.random()+minX);
y=Math.floor((H-minY+1)*Math.random()+minY);
w=Math.floor((maxW+1)*Math.random());
h=Math.floor((maxH+1)*Math.random());
arr[arr.length]=[x,y,w,h];
minX=x;minY=y;maxW=w;maxH=h;
}
return arr
}```
Where the arguments passed are the canvas properties:

X=0 //extreme left
Y=0 //extreme top
W= the canvas width
H= the canvas height

Could not work properly, but at least I hope it illustrates the idea behind.

• I think I understand what you are suggesting and I like it. In fact, that's pretty much what I was going for but without the arrays (I don't completely understand how to use arrays yet) I think what I'm looking for is the math formulas to place the x, y coordinates inside the top left quadrant of the previous rectangle, and have the width and height fall in the bottom right quadrant of that same rectangle, making it inside the rectangle.

•