简体   繁体   English

canvas 上的标记像素

[英]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.我正在围绕 1000x1000 canvas 构建一个应用程序,您可以在其中通过拖动鼠标来实现 canvas 的 select 区域。 In order to remember the area selected from the user I save the coordinates in an array and I draw them with imageData :为了记住从用户中选择的区域,我将坐标保存在一个数组中,并使用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.基本上用户可以点击 canvas 上的像素或将鼠标拖动到 select 像素的矩形。 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.当用户释放鼠标指针时,我将选中的坐标添加到selectedCoordinates中,然后调用applySelectedPixelLayer function 来更新 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.问题是它非常慢,如果选择了很多像素,则需要 20/30 秒才能看到结果。

Is there a more effective way to mark the selected pixel on a canvas?有没有更有效的方法来标记 canvas 上的选定像素?

Like mentioned in the comments, you should try to work with larger areas of image data in one go.就像评论中提到的那样,您应该尝试在一个 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,使用getImageData从 canvas 中获取选定的像素,
  • or (see section after return statement in snippet below), use coordinates to modify existing pixel data或(参见下面代码段中的return语句后的部分),使用坐标修改现有像素数据

 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM