Estoy creando un sitio web con EJS (servidor con Express ) que hace un poco de procesamiento de imágenes. Quiero crear una función en la que el usuario pueda seleccionar parte de una imagen que carga y cuando se presiona un botón para guardar, se guardan las coordenadas del área seleccionada. Pueden hacerlo tantas veces como sea necesario. Pero si no hacen clic en el botón Guardar cuando seleccionan un área nuevamente, se sobrescribirá la anterior. Tengo un problema cuando selecciono: los rectángulos no están en las coordenadas correctas y no funcionan correctamente en general. Actualmente estoy usando canvas HTML para hacer eso, pero cualquier sugerencia es bienvenida. Aquí está el código relacionado:
Formulario (Tenga en cuenta que es EJS no HTML ):
<form id="edit-form" action="/process" method="POST"> <input type="text" id="comment-input" placeholder="Write a comment: " spellcheck="true" /> <button onclick="addComment();" type="button">Add comment</button><br /> <p id="feedback"></p> <ol id="comments-list"></ol> <br /> <canvas id="edit-canvas"></canvas> <br /> <input type="text" name="comments" style="display: none" /> <input type="text" name="image" style="display: none" /> <button type="submit">Submit</button> </form> <script src="./js/edit.js"></script> <script> imageExport.value = "<%- image %>"; const backgroundImage = new Image(); backgroundImage.src = "/downloads/<%- image %>"; backgroundImage.onload = () => { editCanvas.width = backgroundImage.width; editCanvas.height = backgroundImage.height; ctx.drawImage(backgroundImage, 0, 0); }; </script>Código JavaScript:
const editCanvas = document.querySelector("#edit-canvas"); const ctx = editCanvas.getContext("2d"); editCanvas.addEventListener("mousedown", (event) => { const startCoords = { x: event.offsetX, y: event.offsetY }; // draw rect to mouse x and y ctx.fillRect(startCoords.x, startCoords.y, event.clientX, event.clientY); editCanvas.addEventListener("mouseup", (event2) => { ctx.clearRect(startCoords.x, startCoords.y, event.clientX, event.clientY); const endCoords = { x: event2.offsetX, y: event2.offsetY }; ctx.fillRect( startCoords.x, startCoords.y, endCoords.x - startCoords.x, endCoords.y - startCoords.y ); }); });Hay un par de errores en tu código.
Está agregando un oyente mouseup dentro del oyente mousedown . Eso significa que cada vez que alguien hace clic en el lienzo, se crea un nuevo oyente, lo que hace que el oyente del ratón arriba se dispare varias veces.
Simplemente está dibujando el rectángulo al presionar/soltar el lienzo, pero no mientras el usuario mueve el mouse.
Dentro de las funciones de devolución de llamada, está utilizando las propiedades .offsetX y .offsetY del evento para acceder a la posición. Eso está mal, debe utilizar .clientX y .clientY respectivamente. Además, el código no tiene en cuenta la posición en pantalla del elemento del lienzo en sí, que debe restarse de la posición del mouse.
Si repasamos todos los puntos anteriores, obtendremos esto:
const editCanvas = document.querySelector("#edit-canvas"); const ctx = editCanvas.getContext("2d"); const backgroundImage = new Image(); let painting = false; backgroundImage.onload = () => { editCanvas.width = backgroundImage.width; editCanvas.height = backgroundImage.height; ctx.drawImage(backgroundImage, 0, 0); } backgroundImage.src = "https://picsum.photos/id/237/200/300"; let startCoords, canvasPosition; editCanvas.addEventListener("mousedown", (event) => { painting = true; canvasPosition = editCanvas.getBoundingClientRect(); startCoords = { x: event.clientX - canvasPosition.left, y: event.clientY - canvasPosition.top }; }); editCanvas.addEventListener("mousemove", (event) => { if (painting) { canvasPosition = editCanvas.getBoundingClientRect(); let endCoords = { x: event.clientX - canvasPosition.left, y: event.clientY - canvasPosition.top }; ctx.drawImage(backgroundImage, 0, 0); ctx.fillStyle = 'rgba(255,0,0,0.4)'; ctx.fillRect( startCoords.x, startCoords.y, endCoords.x - startCoords.x, endCoords.y - startCoords.y ); } }); editCanvas.addEventListener("mouseup", () => { painting = false; }); <form id="edit-form" action="/process" method="POST"> <input type="text" id="comment-input" placeholder="Write a comment: " spellcheck="true" /> <button onclick="addComment();" type="button">Add comment</button><br /> <p id="feedback"></p> <ol id="comments-list"></ol> <br /> <canvas id="edit-canvas"></canvas> <br /> <input type="text" name="comments" style="display: none" /> <input type="text" name="image" style="display: none" /> <button type="submit">Submit</button> </form>