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

109
Views
canvas use more ctx element

My task is to create two canvases (big and small). In big one create 5 stars of different colors.

Task: by clicking on the star, change the color of the small canvas to the color of the star. Now the problem is that addEventListener only works on the last element. Any ideas?

.html template:

<canvas style="background-color:rgb(255, 255, 255); border: 1px solid black" id='big'>Обновите браузер</canvas>
<canvas style="background-color:rgb(255, 255, 255); border: 1px solid black" id='small'>Обновите браузер</canvas>

.js script:

const big = document.getElementById("big");
const small = document.getElementById("small");

big.height = 600;
big.width  = 600;
small.height = 600;
small.width = 50;

function createStar(moveToX, moveToY, lineToX1, lineToY1, lineToX2, lineToY2, lineToX3, lineToY3, lineToX4, lineToY4, color) {
            ctx = big.getContext('2d');
            ctx.beginPath();
            ctx.moveTo(moveToX, moveToY);
            ctx.lineTo(lineToX1, lineToY1);
            ctx.lineTo(lineToX2, lineToY2);
            ctx.lineTo(lineToX3, lineToY3);
            ctx.lineTo(lineToX4, lineToY4);
            ctx.closePath();
            ctx.strokeStyle = color;
            ctx.fillStyle = color;
            ctx.fill();
            ctx.stroke();
};

const red = new createStar(20, 60, 100, 60, 35, 110, 60, 25, 85, 110, 'red');
const blue = new createStar(120, 60, 200, 60, 135, 110, 160, 25, 185, 110, 'blue');
const green = new createStar(120, 160, 200, 160, 135, 210, 160, 125, 185, 210, 'green');
const black = new createStar(220, 460, 400, 460, 235, 560, 300, 400, 385, 560, 'black');
const yellow = new createStar(220, 260, 300, 260, 235, 310, 260, 225, 285, 310, 'yellow');

big.addEventListener('click', function(e){
            if(ctx.isPointInPath(e.offsetX, e.offsetY)) {
                small.style.backgroundColor = 'red';
            } else {
                small.style.backgroundColor = 'white';
            }
});
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

context.isPointInPath(x, y) will check if the point at coords x and y is inside the current sub-path that's being traced in the context.

Every time you call ctx.beginPath(), this sub-path is cleared.

To workaround that you would have to retrace the whole list of stars and check one by one if the point falls in there.
However, there is also a Path2D interface that you can use.

This interface allows to hold such sub-path as their own object, and can be used by the context instead of the internal context's path by e.g ctx.fill(path), ctx.stroke(path), ctx.clip(path), ctx.scrollPathIntoView(path), ctx.drawFocusIfNeeded(path, element), and you probably guessed it, ctx.isPointInPath(path, x, y), or ctx.isPointInStroke(path, x, y).

So you can rewrite your code so that each star is stored in its own Path2D instance, store all these instances in an Array and then traverse that Array to check if any of these was hit by the point:

const stars = [];
const big = document.getElementById("big");
const small = document.getElementById("small");

big.height = 600;
big.width = 500;
small.height = 600;
small.width = 50;

const ctx = big.getContext("2d");

function createStar(moveToX, moveToY, lineToX1, lineToY1, lineToX2, lineToY2, lineToX3, lineToY3, lineToX4, lineToY4, color) {
  const path = new Path2D();
  // store our path in an object also hodling the color
  stars.push({path, color});
  path.moveTo(moveToX, moveToY);
  path.lineTo(lineToX1, lineToY1);
  path.lineTo(lineToX2, lineToY2);
  path.lineTo(lineToX3, lineToY3);
  path.lineTo(lineToX4, lineToY4);
  ctx.strokeStyle = color;
  ctx.fillStyle = color;
  ctx.fill(path);
  ctx.stroke(path);
};

const red = new createStar(20, 60, 100, 60, 35, 110, 60, 25, 85, 110, 'red');
const blue = new createStar(120, 60, 200, 60, 135, 110, 160, 25, 185, 110, 'blue');
const green = new createStar(120, 160, 200, 160, 135, 210, 160, 125, 185, 210, 'green');
const black = new createStar(220, 460, 400, 460, 235, 560, 300, 400, 385, 560, 'black');
const yellow = new createStar(220, 260, 300, 260, 235, 310, 260, 225, 285, 310, 'yellow');

big.addEventListener('click', function(e) {
  // find the first star that got clicked
  const touched = stars.find((star) =>
    ctx.isPointInPath(star.path, e.offsetX, e.offsetY)
  );
  if (touched) {
    small.style.backgroundColor = touched.color;
  } else {
    small.style.backgroundColor = 'white';
  }
});
canvas {
  background-color: rgb(255, 255, 255);
  border: 1px solid black;
}
<canvas id='big'>Обновите браузер</canvas>
<canvas id='small'>Обновите браузер</canvas>

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!