Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are the rectangles I am creating on this canvas not getting put in the right spot?

I am trying to create a simple page where you click and can create rectangles on a canvas. It takes the user's mouse clicks as input, and then creates a rectangle from the x and y of the click. However, it places the rectangle off to the side by some amount, and I am not sure why.

Fiddle: https://jsfiddle.net/2717s53h/

HTML

<canvas id="cnv"></canvas>

CSS

#cnv{
    width:99vw;
    height:98vh;
    background-color:#faefbd;
}

JAVASCRIPT

$(function () {
    var canvas = $('#cnv');
    var canvObj = document.getElementById('cnv');
    var ctx = canvObj.getContext('2d');

    var point1 = {};
    var point2 = {};

    canvas.click(function (e) {
        console.log(e);

        var x = e.pageX;
        var y = e.pageY;

        console.log(x);
        console.log(y);

        if (Object.keys(point1).length == 0)
        {
            point1.x = x;
            point1.y = y;
        }
        else if (Object.keys(point2).length == 0)
        {
            point2.x = x;
            point2.y = y;

            console.log(point1);
            console.log(point2);
            var width = point2.x - point1.x;
            var height = point2.y - point1.y;
            width = width < 0 ? width * -1 : width;
            height = height < 0 ? height * -1 : height;
            ctx.fillRect(x, y, 10, 10);

            point1 = {};
            point2 = {};
        }

    });
});
like image 506
Jesse Avatar asked Oct 19 '22 00:10

Jesse


1 Answers

There is a difference between the CSS height/ width and the HTML canvas attributes height and width: the former defines the space the canvas occupies in the page; the latter defines the rendering surface. In concreto, suppose you have the following canvas:

<canvas height="400" width="600"></canvas>

with a viewport of a 1200x800 size and the canvas' CSS is set to width: 100%; height: 100%;, then your canvas will be rendered as stretched out twice as big and blurry in both height and width (like in your fiddle; clearly those rectangles are bigger than 10px). As a consequence, the page coordinates are not in sync with the canvas' coordinates.

As per the specification, your fiddle's canvas rendering surface is 300x150 because you didn't specify the width/height attributes:

The width attribute defaults to 300, and the height attribute defaults to 150.

See a slightly 'corrected' version of your fiddle.

As a result my advice (as a non-expert on HTML-canvas) would be to always specify those 2 attributes and not to mess with different rendering surface vs. display dimensions (certainly not relative ones like vw, vh, %, em, ...) if you don't want unpredictable results; although some SO users have been looking for a solution.

like image 135
webketje Avatar answered Oct 21 '22 17:10

webketje