Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

148
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!