javascriptcanvasshapessketching

Trying to SKETCH a rectangle on canvas, preferably in Javascript?


I am trying to sketch a rectangle, like how you do in Paint. But currently when I try to sketch a rectangle, this is what my canvas looks like--double drawings, messy rectangles.

This is what my whole code looks like:

(deleted code)

How do I sketch a rectangle that looks like this: like one rectangle?


Solution

  • First of all I think it's more clear if you store the coordinates in separated variables instead of an array (startX, startY, lastX, lastY).

    Also you should subtract the canvas position from the mouse position to get the coordinate inside the canvas, right now it kind of work because the canvas is at the top of the page.

    I see you want to keep the old content, I used a canvas to store the previous drawn content, then before you draw the current rectangle you must redraw the old content (using ctx.drawImage).

    You should add 0.5 to the coordinates so the lines do not get blurry, this only happens if you draw a line with an odd width (1, 3, 5). this is because if you try to draw 1px line on say coordinate x=1 you must draw half a pixel to both sides (0.5 to 1.5), so it looks blurry.

    but if you draw it at say x=0.5 you draw the line from 0 to 1 which is exactly one pixel.

    var isDown = false;
    var startX, startY;
    var lastX, lastY;
    
    var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');
    var canvasRect = canvas.getBoundingClientRect();
    
    var backBuffer = canvas.cloneNode(true);
    var backBufferCtx = backBuffer.getContext('2d');
    
    canvas.addEventListener('mousedown', function down() {
        startX = event.clientX - canvasRect.left;
        startY = event.clientY - canvasRect.top;
        isDown = true;
    });
    
    canvas.addEventListener('mouseup', function up() {
        isDown = false;
    
        // Draw Current Canvas Content
        updateCanvas();
    
        // Save current content
        backBufferCtx.clearRect(0, 0, backBuffer.width, backBuffer.height);
        backBufferCtx.drawImage(canvas, 0, 0);
    });
    
    canvas.addEventListener('mousemove', function move() {
        if (! isDown) return;
    
        lastX = event.clientX - canvasRect.left;
        lastY = event.clientY - canvasRect.top;
        updateCanvas();
    });
    
    function updateCanvas() {
        // Clear the canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    
        // Draw Current Canvas Content
        ctx.drawImage(backBuffer, 0, 0);
    
        // Draw New Rectangle
        ctx.beginPath();
        // add 0.5 so the line do not get blurry
        ctx.rect(startX + 0.5, startY + 0.5, lastX - startX, lastY - startY);
        ctx.stroke();
    }
    <canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000; margin-top: 100px"></canvas>