A Demo: http://jsfiddle.net/m1erickson/SdPPa/
Your instinct of creating rectangle objects to define what is drawn on the canvas is indeed the common standard.
Unlike Java, JavaScript does not have true classes, but you can create a pseudo-class as you have done in your question.
At it's simplest a Rectangle "class" needs these properties:
If you want to animate those rectangles on the canvas you might add:
- velocityX, directionY
- velocityY, direction
These new properties allow you to move the rectangles like this:
this.x += this.directionX * this.velocityX;
this.y += this.directionY * this.velocityY;
Hint: Html5 now has an excellent animation handler: requestAnimationFrame. You might want to use this instead of setInterval or setTimeout because it gives better performance by integrating itself with the refresh cycle of the browser.
Hint: JavaScript is a prototypal language so you can extend your "class" with methods. The best way to add methods to a "class" is to add them to the classes prototype. That way the methods are created once and shared by all instances of the class rather than having every method recreated on every instance.
So a method to allow a rectangle instance to draw itself to the canvas might look like this:
// draw this rect on the canvas
Rectangle.prototype.render=function(){
ctx.fillStyle=this.color;
ctx.fillRect(this.x,this.y,this.width,this.height);
return(this);
}
Hint: JavaScript "class" methods can be chained if you always return(this). A good use of chaining might be calling a move
method on an instance and then chaining on the render
method.
rectangle1.move().render();
There's lots to learn about javascript "classes".
Here's annotated code to start with:
Good luck with your project!
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
// canvas related variables
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// an array to hold all rectangle objects
var rectangles=[];
// a rectangle pseudo-class (javascript does not have actual classes)
function Rectangle(stdProperties) {
addProperties(this,stdProperties);
this.color=randomColor();
};
//
// Add methods that apply to all instance rectangles
// to Rectangle.prototype so those methods are
// created once for all instances instead of
// repeatedly for every instance.
//
// set x,y,width,height of this rectangle
Rectangle.prototype.init=function(x,y,width,height){
this.x=x;
this.y=y;
this.width=width;
this.height=height;
return(this);
};
// move this rectangle by its preset delta-x and delta-y
Rectangle.prototype.move=function(){
var maxRight=canvas.width-this.width;
var maxBottom=canvas.height-this.height;
this.x+=this.directionX*this.velocityX;
if(this.x<0){ this.x=0; this.directionX*=-1}
if(this.x>maxRight){ this.x=maxRight; this.directionX*=-1}
this.y+=this.directionY*this.velocityY;
if(this.y<0){ this.y=0; this.directionY*=-1}
if(this.y>maxBottom){ this.y=maxBottom; this.directionY*=-1}
return(this);
};
// draw this rect on the canvas
Rectangle.prototype.render=function(){
ctx.fillStyle=this.color;
ctx.fillRect(this.x,this.y,this.width,this.height);
return(this);
}
// create a new rectangle object from the Rectangle "class"
function newRect(x,y,width,height){
// define default properties for Rectangle
var DefaultRectangleProperties={
x:0,y:0,width:10,height:10,
velocityX:1,velocityY:1,directionX:1,directionY:1,
color:"black",
}
// new-up a Rectangle
var rect = new Rectangle(DefaultRectangleProperties);
// set the x,y,width,height & draw it on the canvas
rect.init(x,y,width,height).render();
// return(this) to allow chaining
return(rect);
}
// TESTING
// create 5 rectangles with some randomness
for(var i=0;i<5;i++){
var rect=newRect(Math.random()*200,Math.random()*200,40,50);
rect.velocityX=Math.random()*2;
rect.velocityY=Math.random()*3;
rectangles.push(rect);
}
// animate the rectangles using requestAnimationFrame
animate();
// the animation loop
function animate(t){
// request another animation frame
requestAnimationFrame(animate);
// clear the canvas
// move all the rectangles by their preset distance
// redraw all the rectangles
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<rectangles.length;i++){
rectangles[i].move().render();
}
}
///////////////////////////////////
// Utilities
///////////////////////////////////
// create getters/setters on the specified object
// using the supplied properties object
//
function addProperties(object,properties){
for (var i in properties) {
(function(i) {
Object.defineProperty(object, i, {
get: function(){ return properties[i]; },
set: function(val){ properties[i] = val; }
})
})(i);
}
}
// generate a random color
function randomColor(){
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>