Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

112
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda