简体   繁体   中英

Draw multiple shapes on canvas with mouse - clearrect doesnt clear on fast moves

Im having a canvas, where i can draw rectangles using the mouse.

I would like the user to be able to draw multiple rectangles on the same canvas. On all the 'draw rect with mouse' examples i found, you would usually clear the whole canvas with clearRect(0,0,canvas.width,canvas.height), but since i want to be able to draw multiple rects, i changed that to canvas.clearRect(start.x, start.y, end.x-start.x, end.y-start.y).

The problem is if you make any fast moes its like being on windows 95 again. The rect doesnt get cleared properbly.

You can see the code and problem here: http://jsfiddle.net/2r5n1rmL/

as you can see, i tried to add a little extra to the clearrect, which helped a bit, but not enough

draw.clearRect(start.x-5, start.y-5, w+10, h+10);

How do i solve this?

Thank you

You need to keep track of your last drawn height and width and clear it based on that, instead of the current height and width.

With

var lastWidth = 0;
var lastHeight = 0;

your mousemove changes to

$("#drawing").mousemove(function(e) {
    ...
    draw.clearRect(start.x-5, start.y-5, lastWidth + 6, lastHeight + 6);
    ...
    draw.rect(start.x, start.y, w, h);
    lastWidth = w;
    lastHeight = h;
    ...

Fiddle - http://jsfiddle.net/6vq64sdh/


Note that your drawing logic has a bit of a problem when you drag up and because of the additional +5 offset you give in the draw is direction biased (you won't have problems when you are drawing a rectangle from top left to bottom right, but you will have a problem when you do the reverse)

First of all, drawing a rectangle has a start and an end. When you click, you start drawing. When you release the mouse button, drawing stops.

Secondly, you should draw a rectangle starting from the minimum x and minimum y. So, I believe you should have a flag to know whether you are drawing:

var amIDrawing = false;

Then, you should have an onmousedown attached to your canvas, which would be a function like this:

function mousePressed(e) {
    amIDrawing = true;
}

and you must acknowledge with an onmouseup attached to your canvas, which would be a function like this:

function mouseReleased(e) {
    amIDrawing = false;
}

Finally, you should have an onmousemove attached to your canvas, which would be a function like this:

function mouseMoved(e) {
    //Clear previous rectangle if needed
    //draw new rectangle
}

Note, that in mousePressed you need to store the coordinates and you need to pair those coordinates with the coordinates you receive when you move your mouse to know what new rectangle you need to display.

I too had this, so what I did is instead of clearing that specific rectangle I stored all the rectangle's positions in an array and updated those individual positions, and redrawn all of them on every mouse movement.

 var can = document.getElementById("can"); var cont = can.getContext("2d"); var isCon = false; var shapes = []; var cur = 0; cont.canvas.width = window.innerWidth; cont.canvas.height = window.innerHeight; function updateFrame() { shapes.forEach((el) => { cont.strokeRect(el.x1, el.y1, el.x2 - el.x1, el.y2 - el.y1); }); } can.addEventListener("pointerdown", function (e) { isCon = true; shapes.push({ x1: e.clientX - can.offsetLeft, y1: e.clientY - can.offsetTop, x2: e.clientX - can.offsetLeft, y2: e.clientY - can.offsetTop, }); }); can.addEventListener("pointermove", function (e) { if (isCon) { cont.clearRect(0, 0, can.width, can.height); shapes[cur].x2 = e.clientX - can.offsetLeft; shapes[cur].y2 = e.clientY - can.offsetTop; requestAnimationFrame(updateFrame); } }); can.addEventListener("pointerup", function (e) { isCon = false; cur += 1; });
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> html, body { margin: 0px; width: 100%; height: 100%; } </style> </head> <body id="body"> <canvas id="can"></canvas> </body> </html>

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