ChatGPT解决这个技术问题 Extra ChatGPT

如何将一个画布的内容本地复制到另一个画布

我想复制一个画布的所有内容并将它们转移到客户端的另一个画布上。我认为我会使用 canvas.toDataURL()context.drawImage() 方法来实现这一点,但我遇到了一些问题。

我的解决方案是获取 Canvas.toDataURL() 并将其存储在 Javascript 中的 Image 对象中,然后使用 context.drawImage() 方法将其放回原处。

但是,我相信 toDataURL 方法会返回一个 64 位编码的标签,并在其前面加上 "data:image/png;base64,"。这似乎不是一个有效的标签,(我总是可以使用一些正则表达式来删除它),但是在 "data:image/png;base64," 子字符串之后的 64 位编码字符串是一个有效的图像吗?我可以说image.src=iVBORw...ASASDAS,然后在画布上画回它吗?

我查看了一些相关问题:Display canvas image from one canvas to another canvas using base64

但解决方案似乎并不正确。


C
Chalist

实际上,您根本不必创建图像。 drawImage() 将接受 CanvasImage 对象。

//grab the context from your destination canvas
var destCtx = destinationCanvas.getContext('2d');
    
//call its drawImage() function passing it the source canvas directly
destCtx.drawImage(sourceCanvas, 0, 0);

比使用 ImageData 对象或 Image 元素快得多。

请注意,sourceCanvas 可以是 HTMLImageElementHTMLVideoElementHTMLCanvasElement。正如 Dave 在此答案下方的评论中所提到的,您不能使用画布绘图上下文作为来源。如果您有一个画布绘图上下文而不是创建它的画布元素,则在 context.canvas 下的上下文中有对原始画布元素的引用。

这是一个 jsPerf 来演示为什么这是克隆画布的唯一正确方法:http://jsperf.com/copying-a-canvas-element


一个让我大吃一惊的小问题:虽然您可以绘制画布 (HTMLCanvasElement),但您不能 绘制上下文 (CanvasRenderingContext2D)。请改用 myContext.canvas
@Dave 评论是必读...如果可能的话,我会给出+10 ;)。 @Robert-Hurst 必须用此评论补充他的答案,因为他没有指定 source canvas 来自哪里......
你能举个例子吗?
@RogerGajraj 实际上画布不必是可见的。那里证明了这一点=> jsfiddle.net/d36wwtvj
C
Community

@robert-hurst 有一个更干净的方法。

但是,也可以在复制后确实希望拥有 Data Url 副本的地方使用此解决方案。例如,当您构建一个使用大量图像/画布操作的网站时。

    // select canvas elements
    var sourceCanvas = document.getElementById("some-unique-id");
    var destCanvas = document.getElementsByClassName("some-class-selector")[0];

    //copy canvas by DataUrl
    var sourceImageData = sourceCanvas.toDataURL("image/png");
    var destCanvasContext = destCanvas.getContext('2d');

    var destinationImage = new Image;
    destinationImage.onload = function(){
      destCanvasContext.drawImage(destinationImage,0,0);
    };
    destinationImage.src = sourceImageData;

我需要复制画布的内容以在其他地方使用 - 这非常完美,因为它生成了大约 80KB 的数据,而使用 getImageData 生成了大约 60MB 的数据