es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Problema con JavaScript (JQuery) mientras trabaja en el lienzo de HTML5.

Estoy creando una herramienta de dibujo utilizando HTML, CSS y JavaScript (JQuery) en un lienzo.

En la versión de escritorio, comienza a dibujar cuando hago clic en el lienzo y continúa dibujando incluso si suelto el clic y muevo el ratón (quiero que solo dibuje cuando estoy sosteniendo el clic y moviendo el ratón).

En cuanto al móvil, comienza a dibujar después de 2 toques (no sé por qué) y dibuja como se espera, es decir, solo cuando lo estoy sosteniendo. Pero aquí el problema es que cuando toco en otro lugar, en lugar de dibujar un punto donde toqué, dibuja una línea desde donde me detuve anteriormente hasta la ubicación actual (por ejemplo, si me detuve en la esquina inferior izquierda de la página anteriormente y toco nuevamente en la esquina superior derecha de la página para comenzar, dibuja una línea a través).

He agregado muchas cosas (relevantes o no, no lo sé) mirando otras respuestas, pero no funciona. Por favor, ayúdame con estos 2 problemas. Gracias.

Aquí está el código JS después de eliminar la parte que sé que no está causando problemas:

$(document).ready(function(){

let color = "negro";
let x;
let y;
let isPressed;

const canvas = $("canvas");
const colorElement = $("#color");
const ctx = canvas[0].getContext("2d");
const canvass = document.getElementById("myCanvas");

ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;

let prevX,prevY;

canvas.on("mousedown",(e)=>{
    isPressed = true;
    prevX = x;
    prevY = y;
    x = e.pageX - ctx.canvas.offsetLeft;
    y = e.pageY - ctx.canvas.offsetTop;
});
$("document").on("mouseup",(e)=>{
    isPressed = false;
    x = undefined;
    y = undefined;
});
canvas.on("mousemove",(e)=>{
    if(isPressed){
        e.preventDefault();    /*added this after looking at other answers*/
        e.stopPropagation();   /*added this after looking at other answers*/
        x = e.pageX - ctx.canvas.offsetLeft;
        y = e.pageY - ctx.canvas.offsetTop;
        drawCircle(x,y);
        drawLine(prevX,prevY,x,y);
        prevX = x;
        prevY = y;
    }
});

/*for the app to work on mobile devices*/
canvass.addEventListener("touchmove", function (e) {
    var touch = e.touches[0];
    var mouseEvent = new MouseEvent("mousemove", {
        clientX: touch.clientX,
        clientY: touch.clientY
    });
    canvass.dispatchEvent(mouseEvent);
}, false);
canvass.addEventListener("touchdown", function (e) {
    var touch = e.touches[0];
    var mouseEvent = new MouseEvent("mousedown", {
        clientX: touch.clientX,
        clientY: touch.clientY
    });
    canvass.dispatchEvent(mouseEvent);
}, false);
canvass.addEventListener("touchup", function (e) {
    var touch = e.touches[0];
    var mouseEvent = new MouseEvent("mouseup", {
        clientX: touch.clientX,
        clientY: touch.clientY
    });
    canvass.dispatchEvent(mouseEvent);
}, false);

function drawCircle(x,y){
    ctx.beginPath();
    ctx.arc(x,y,size,0,Math.PI * 2);
    ctx.fillStyle = color;
    ctx.fill();
    ctx.closePath();
}

function drawLine(x,y,x2,y2){
    ctx.beginPath();
    ctx.moveTo(x,y);
    ctx.lineTo(x2,y2);
    ctx.strokeStyle = color;
    ctx.lineWidth = size*2;
    ctx.stroke();
    ctx.closePath();
}
colorElement.on("change",(e)=>{
    color = e.target.value;
});

});
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Solución para Herramienta de Dibujo

    Problema 1: dibujar sin mantener clicado

    En el escritorio, este código comienza a dibujar incluso cuando se suelta el clic y el ratón se mueve:

    canvas.on("mousedown",(e)=>{
        isPressed = true;
        prevX = x;
        prevY = y;
        x = e.pageX - ctx.canvas.offsetLeft;
        y = e.pageY - ctx.canvas.offsetTop;
    });
    $("document").on("mouseup",(e)=>{
        isPressed = false;
        x = undefined;
        y = undefined;
    });
    canvas.on("mousemove",(e)=>{
        if(isPressed){
            e.preventDefault();
            e.stopPropagation();
            x = e.pageX - ctx.canvas.offsetLeft;
            y = e.pageY - ctx.canvas.offsetTop;
            drawCircle(x,y);
            drawLine(prevX,prevY,x,y);
            prevX = x;
            prevY = y;
        }
    });
    

    Para solucionar este problema, necesitamos escuchar los eventos mousemove en el documento, además del canvas. De esta manera, podremos detectar cuando el usuario ha soltado el clic mientras mueve el ratón y detener el dibujo.

    $(document).on("mousemove",(e)=>{
        if(isPressed){
            x = e.pageX - ctx.canvas.offsetLeft;
            y = e.pageY - ctx.canvas.offsetTop;
            drawCircle(x,y);
            drawLine(prevX,prevY,x,y);
            prevX = x;
            prevY = y;
        }
    });
    

    Problema 2: dibujar líneas al tocar fuera del canvas

    El código tiene esta sección, que debería permitir que la aplicación funcione en dispositivos móviles:

    const canvass = document.getElementById("myCanvas");
    
    canvass.addEventListener("touchmove", function (e) {
        var touch = e.touches[0];
        var mouseEvent = new MouseEvent("mousemove", {
            clientX: touch.clientX,
            clientY: touch.clientY
        });
        canvass.dispatchEvent(mouseEvent);
    }, false);
    canvass.addEventListener("touchdown", function (e) {
        var touch = e.touches[0];
        var mouseEvent = new MouseEvent("mousedown", {
            clientX: touch.clientX,
            clientY: touch.clientY
        });
        canvass.dispatchEvent(mouseEvent);
    }, false);
    canvass.addEventListener("touchup", function (e) {
        var touch = e.touches[0];
        var mouseEvent = new MouseEvent("mouseup", {
            clientX: touch.clientX,
            clientY: touch.clientY
        });
        canvass.dispatchEvent(mouseEvent);
    }, false);
    

    El problema es que está escuchando los eventos touchstart usando el nombre incorrecto (touchdown en lugar de touchstart). Además, necesitamos prevenir el comportamiento por defecto al tocar fuera del canvas, para evitar dibujar líneas en lugar de puntos.

    canvass.addEventListener("touchstart", function (e) {
        if (e.target == canvas[0]) {
            var touch = e.touches[0];
            var mouseEvent = new MouseEvent("mousedown", {
                clientX: touch.clientX,
                clientY: touch.clientY
            });
            canvas[0].dispatchEvent(mouseEvent);
        }
        e.preventDefault();
    }, false);
    

    Esto solo comenzará a dibujar si el evento touch ocurre en el canvas. Si el evento touch ocurre fuera del canvas, evitará el comportamiento por defecto y no dibujará una línea.

    Aquí está el código actualizado con ambas soluciones aplicadas:

    $(document).ready(function(){
    
        let color = "black";
        let size = 10;
        let x;
        let y;
        let isPressed;
    
        const canvas = $("canvas");
        const colorElement = $("#color");
        const ctx = canvas[0].getContext("2d");
        const canvass = document.getElementById("myCanvas");
    
        ctx.canvas.width = window.innerWidth;
        ctx.canvas.height = window.innerHeight;
    
        let prevX,prevY;
    
        canvas.on("mousedown",(e)=>{
            isPressed = true;
            prevX = x;
            prevY = y;
            x = e.pageX - ctx.canvas.offsetLeft;
            y = e.pageY - ctx.canvas.offsetTop;
        });
        $(document).on("mouseup",(e)=>{
            isPressed = false;
            x = undefined;
            y = undefined;
        });
        canvas.on("mousemove",(e)=>{
            if(isPressed){
                x = e.pageX - ctx.canvas.offsetLeft;
                y = e.pageY - ctx.canvas.offsetTop;
                drawCircle(x,y);
                drawLine(prevX,prevY,x,y);
                prevX = x;
                prevY = y;
            }
        });
    
        canvass.addEventListener("touchstart", function (e) {
            if (e.target == canvas[0]) {
                var touch = e.touches[0];
                var mouseEvent = new MouseEvent("mousedown", {
                    clientX: touch.clientX,
                    clientY: touch.clientY
                });
                canvas[0].dispatchEvent(mouseEvent);
            }
            e.preventDefault();
        }, false);
    
        canvass.addEventListener("touchmove", function (e) {
            if (e.target == canvas[0]) {
                var touch = e.touches[0];
                var mouseEvent = new MouseEvent("mousemove", {
                    clientX: touch.clientX,
                    clientY: touch.clientY
                });
                canvas[0].dispatchEvent(mouseEvent);
            }
            e.preventDefault();
        }, false);
    
        canvass.addEventListener("touchend", function (e) {
            if (e.target == canvas[0]) {
                var mouseEvent = new MouseEvent("mouseup", {});
                canvas[0].dispatchEvent(mouseEvent);
            }
            e.preventDefault();
        }, false);
    
        function drawCircle(x,y){
            ctx.beginPath();
            ctx.arc(x,y,size,0,Math.PI * 2);
            ctx.fillStyle = color;
            ctx.fill();
            ctx.closePath();
        }
    
        function drawLine(x,y,x2,y2){
            ctx.beginPath();
            ctx.moveTo(x,y);
            ctx.lineTo(x2,y2);
            ctx.strokeStyle = color;
            ctx.lineWidth = size*2;
            ctx.stroke();
            ctx.closePath();
        }
    
        colorElement.on("change",(e)=>{
            color = e.target.value;
        });
    });
    

Comments are closed.