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

113
Visualizações
Marking pixel on a canvas

I'm building an application around a 1000x1000 canvas, where you can select areas of the canvas by dragging the mouse around. In order to remember the area selected from the user I save the coordinates in an array and I draw them with imageData:

    const applySelectedPixelLayer = useCallback(() => {
        const canvas = canvasRef.current;
        if (!canvas) return;
        const ctx = canvas.getContext("2d");
        const imageData = ctx.createImageData(1, 1);

        imageData.data[0] = 0; // R value
        imageData.data[1] = 0; // G value
        imageData.data[2] = 0; // B value
        imageData.data[3] = 255; // A value

        for (let i = 0; i < selectedCoordinates.length; i++) {
            ctx.putImageData(
                imageData,
                selectedCoordinates[i][0],
                selectedCoordinates[i][1]
            );
        }
    }, [selectedCoordinates]);

Basically the user can click pixel on the canvas or drag the mouse to select a rectangle of pixels. When the user releases the mouse pointer, I add the coordinates selected to selectedCoordinates and then I call the applySelectedPixelLayer function to update the canvas.

The problem is that it's incredibly slow, it takes 20/30 seconds to see the result if a lot of pixels are selected.

Is there a more effective way to mark the selected pixel on a canvas?

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

Like mentioned in the comments, you should try to work with larger areas of image data in one go.

Here's an example that lets you cut out a part of some random image.

  • Store drag start
  • Store drag end
  • Use getImageData to get the selected pixels from the canvas,
  • or (see section after return statement in snippet below), use coordinates to modify existing pixel data

const cvs = document.createElement("canvas");
cvs.width = cvs.height = 512;
const ctx = cvs.getContext("2d");

let imageData = null;
let offset = [];
let dragStart = null;
let dragPos = null;
let copied = null;

// Generate some image
const init = () => {
  const size = cvs.width / 8;
  
  for (let i = 0; i < 64; i += 1) {
    const y = Math.floor(i / 8);
    const x = i % 8;
    
    ctx.fillStyle = `hsl(${Math.random() * 255} 100% 50%)`;
    ctx.fillRect(x * size, y * size, size, size);
  }
  
  imageData = ctx.getImageData(0, 0, cvs.width, cvs.height);
  ctx.clearRect(0, 0, cvs.width, cvs.height);
  
  draw();
}

const draw = () => {
  ctx.clearRect(0, 0, cvs.width, cvs.height);
  ctx.putImageData(imageData, 0, 0);
  
  if (dragStart && dragPos) {
    const [ x1, y1 ] = dragStart;
    const [ x2, y2 ] = dragPos;
  
    ctx.fillStyle = "rgba(255,255,255,0.9)";
    ctx.strokeStyle = "rgba(255, 255, 255)";
    ctx.lineWieght = 2;
    ctx.fillRect(x1, y1, x2 - x1, y2 - y1);
    ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
  }
}

const onMove = e => {
  const [ dx, dy ] = offset;
  
  dragPos = [
    e.clientX - dx,
    e.clientY - dy
  ];
  
  draw();
}

const onSelectionEnd = e => {
  const [ x1, y1 ] = dragStart;
  const [ x2, y2 ] = dragPos;
  
  dragStart = null;
  dragPos = null;
  
  
  // A) To get the image you selected, you can do:
  draw();
  const selection = ctx.getImageData(
    Math.min(x1, x2),
    Math.min(y1, y2),
    Math.abs(x1 - x2),
    Math.abs(y1 - y2)
  );

  imageData = selection;
  return;
  
  // B) To clear the pixels from the original image, you could do something like:  
  for (let y = Math.min(y1, y2); y < Math.max(y1, y2); y += 1) {
    for (let x = Math.min(x1, x2); x < Math.max(x1, x2); x += 1) {
      const pi = y * cvs.width * 4 + x * 4;
      
      imageData.data[pi + 0] = 255;
      imageData.data[pi + 1] = 255;
      imageData.data[pi + 2] = 255;
      imageData.data[pi + 3] = 255;
    }
  }
  

}

cvs.addEventListener("mousedown", e => {
  const { top, left } = cvs.getBoundingClientRect();
  offset = [ top, left ];

  onMove(e);
  dragStart = dragPos;
  
  cvs.addEventListener("mousemove", onMove);
  window.addEventListener("mouseup", onSelectionEnd, { once: true });
});


init();
document.body.appendChild(cvs);

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