简体   繁体   中英

Drawing is zoomed in canvas HTML/JavaScript

Currently I'm trying to draw on canvas... But the problem is that drawing is zoomed in. Basically beginPath is not following the cursor. This happened when I changed canvas width and height in css . Before that, size was specified in canvas tag without any pixel values. But in css I have vh and % values. Is there any way to make it act normal again. Here's my html code:

<canvas id="canvas" style="background-color: white; border:2px solid;"></canvas>

Here's my css code:

#canvas {
    width: 100%;
    height: 90vh;
    cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='48' viewport='0 0 100 100' style='fill:black;font-size:24px;'><text y='50%'>✍️</text></svg>") 0 20, auto;
}

And last but not least, here's my Js code(how I'm writing on canvas):

const points = [];
const canvas = document.getElementById("canvas");
const mouse = { x: 0, y: 0, button: false }
const ctx = canvas.getContext("2d");
canvas.addEventListener("mousemove", mouseEvents);
canvas.addEventListener("mousedown", mouseEvents);
canvas.addEventListener("mouseup", mouseEvents);
var x = "black",
    y = 5 / 2;

function mouseEvents(e) {
    mouse.x = e.pageX - 1;
    mouse.y = e.pageY - 1;
    const lb = mouse.button;
    mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
    if (mouse.button) {
        if (!lb) { points.length = 0 }
            points.push({ x: mouse.x, y: mouse.y });
            drawPoints();
        }
    }

function drawPoints() {
    ctx.strokeStyle = x;
    ctx.lineWidth = y;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.beginPath();
    if (mode == "pen") {
        ctx.globalCompositeOperation = "source-over";
        for (const p of points) { ctx.lineTo(p.x, p.y); }
        ctx.stroke();
    } else {
        ctx.globalCompositeOperation = "destination-out";
        ctx.arc(mouse.x, mouse.y, 8, 0, Math.PI * 2, false);
        ctx.stroke();
        ctx.fill();
    }
}

function color(obj) {
    switch (obj.id) {
        case "green":
            x = "green";
            break;
        case "blue":
            x = "blue";
            break;
        case "red":
            x = "red";
            break;
        case "yellow":
            x = "yellow";
            break;
        case "orange":
            x = "orange";
            break;
        case "black":
            x = "black";
            break;
        case "white":
            x = "white";
            break;
        case "grey":
            x = "grey";
            break;
    }
    document.getElementById("current_color").style.background = x;
}

function erase() {
    var m = confirm("Want to clear");
    if (m) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        document.getElementById("canvasimg").style.display = "none";
    }
}

canvas.addEventListener("touchstart", function (e) {
    mousePos = getTouchPos(canvas, e);
    var touch = e.touches[0];
    var mouseEvent = new MouseEvent("mousedown", {
        clientX: touch.clientX,
        clientY: touch.clientY
    });
    canvas.dispatchEvent(mouseEvent);
        }, false);
canvas.addEventListener("touchend", function (e) {
    var mouseEvent = new MouseEvent("mouseup", {});
    canvas.dispatchEvent(mouseEvent);
}, false);
canvas.addEventListener("touchmove", function (e) {
    var touch = e.touches[0];
    var mouseEvent = new MouseEvent("mousemove", {
        clientX: touch.clientX,
        clientY: touch.clientY
    });
    canvas.dispatchEvent(mouseEvent);
}, false);

// Get the position of a touch relative to the canvas
function getTouchPos(canvasDom, touchEvent) {
    var rect = canvasDom.getBoundingClientRect();
    return {
        x: touchEvent.touches[0].clientX - rect.left,
        y: touchEvent.touches[0].clientY - rect.top
    };
}

document.getElementById("canvas").onwheel = function (event) {
    event.preventDefault();
};

document.getElementById("canvas").onmousewheel = function (event) {
    event.preventDefault();
};

canvas.addEventListener("touchstart", function (event) { event.preventDefault() })
canvas.addEventListener("touchmove", function (event) { event.preventDefault() })
canvas.addEventListener("touchend", function (event) { event.preventDefault() })
canvas.addEventListener("touchcancel", function (event) { event.preventDefault() })

var mode = "pen";
$("#pen").click(function () {
    mode = "pen";
    $('canvas').css('cursor', "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='48' viewport='0 0 100 100' style='fill:black;font-size:24px;'><text y='50%'>✍🏻</text></svg>\") 0 20, auto");
});
$("#eraser").click(function () {
    mode = "eraser"
    $('canvas').css('cursor', "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='48' viewport='0 0 100 100' style='fill:black;font-size:18px;'><text y='50%'>🧽</text></svg>\") 0 15, auto");
});

Don't use relative units for your canvas directly. Apply those relative units (% and vh) to a container of your canvas, then from javascript resize your canvas.

 const container = document.getElementById("app"); (function () { window.addEventListener("resize", resizeCanvas, false); function resizeCanvas() { const canvas = document.getElementById("canvas"); const context = canvas.getContext("2d"); canvas.width = container.clientWidth; canvas.height = container.clientHeight; //DRAW ALL context.fillRect(0,0,canvas.width, canvas.height) } resizeCanvas(); })();
 #app { width: 50vw; height: 50vh; }
 <div id="app"> <canvas id="canvas" /> </div>

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