简体   繁体   中英

Drawing Rects on HTML5 canvas

Is it possible to store a rectangle in a variable in order to access that variable and move it around? Something like:

var rect = new Rect();
/* then in update() method */
rect.x += 5;
rect.y += 5;

Is something like this possible, or do you have to create a new rectangle using context each time? If this is the only possible way, I don't understand how you can target each rectangle drawn in the canvas. Can someone please explain this to me?

HTML5 Cancas has a bitmap model : when you draw you modify the pixels of the canvas, and you can read the pixels if you want, but the logic of the pixels (lines, rects, etc.) is lost.

The canvas model is very fast, enables to do complex things that would be too long in an object/vectoriel model but the limit is that you can't change or remove drawn objects like rects.

If you want to do so, you need to use a vectoriel/object model, like SVG (or plain DOM objects).

If you want to use canvas and objects, a solution is to keep your rect variables (like the one you did) in plain javascript (outside your canvas) and simply redraw the whole canvas each time you change a rect. It's efficient and common for applications using canvas (for example games).

Here's a complete exemple : 3 rects are moved and redrawn every 10 ms.

http://jsfiddle.net/dystroy/PkzDA/

I made it very simple but clean and efficient. You can use this kind of logic in real and fast applications (I do).

I would save a model of all the rectangles you want to draw with their coordinates. Then, you just have to listen to the mouseclick event (or mouseover event, whatever your needs) and browse through each element of your model to see if the mouse click was done inside the coordinates of a rectangle.

As the previous posters said, you have to redraw your canvas every time you want to make a change to it (although you can speed things up by redrawing only the region of interest). Hope that helps a bit!

EDIT:

you could have a rectangle object defined:

function Rectangle(x, y, w, h) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;

    this.contains = function(x, y) {
        return (x > this.x && x <= (this.x + this.w) &&
            y > this.y && y <= (this.y + this.h));
    }

    this.clone = function() {
        return new Dimension(this.x, this.y, this.w, this.h);
    }
}

and then have an array that would be your model :

var model = [];

And then add your rectangles to it:

model.push(new Rectangle(10,10,10,10));//x, y, width, height

Then, when you click on your canvas, you retrieve the mouse click coordinates from the mouse event and you loop over your array to see if the click was done inside one of the rectangles:

for (i = 0 ; i < model.length ; i++) {
 if (model[i].contains(mouseEvent.x, mouseEvent.y))
  //do something like redraw your canvas
}

I found that this tutorial really helped me get my head around the subject.

http://simonsarris.com/blog/510-making-html5-canvas-useful

He walks through the creation of objects, keeping track of the state, handling mouse events, etc.

如果要在画布上移动矩形,则每次更改x或y时都需要清除并重绘该矩形。

First you have to combine what I will say with what @Gaet said

Now about reducing context effort: An option to reuse the same canvas context without erasing it is to change the way the rectangle is drawn.

You have to change the composition style to 'xor' so whenever you draw the rectangle twice it will disappear an you will be able to paint it to a new location.

See bellow example:

//this will switch context to xor mode
ctx.globalCompositeOperation = 'xor';

//this will paint the rectangle
ctx.fillRect(0, 0, 100, 100);

//this will remove the rectangle
ctx.fillRect(0, 0, 100, 100);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM