Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

149
Vistas
How to make multiple selection rects?

I'm making a website with EJS (server with Express) which does a little bit of image processing. I want to make a feature where the user can select part of an image they upload and when a button to save is pressed the coordinates of the selected area are saved. They can do that as many times as needed. But if they don't click on the save button when they select an area again the old one will be overwritten. I have a problem when I select - the rectangles aren't at the correct coordinates and aren't working properly in general. I'm currently using HTML canvas to do that but any suggestions are welcome. Here's the code related:

Form (Note that it is EJS not 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>

JavaScript code:

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
        );
    });
});
about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

There are a couple of mistakes in your code.

(1)

You're adding a mouseup listener inside the mousedown listener. That means everytime someone clicks on the canvas it creates a new listener, leading to the mouseup listener being fired multiple times.

(2)

You're just drawing the rectangle upon pressing/releasing the canvas but not while the user is actually moving the mouse.

(3)

Inside the callback functions you're using the event's .offsetX and .offsetY properties to access the position. That's wrong, you need to utilize .clientX and .clientY respectively. Furthermore the code doesn't take into account the on-screen position of the canvas element itself, which needs to be substracted from the mouse position.

If we go over all the points above we'll come up with this:

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>

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda