ChatGPT解决这个技术问题 Extra ChatGPT

How to Copy Contents of One Canvas to Another Canvas Locally

I'd like to copy ALL contents of one canvas and transfer them to another all on the client-side. I would think that I would use the canvas.toDataURL() and context.drawImage() method to implement this but I am running into a few issues.

My solution would be to get Canvas.toDataURL() and store this in an Image object in Javascript, and then use the context.drawImage() method to place it back.

However, I believe the toDataURL method returns a 64 bit encoded tag with "data:image/png;base64," prepended to it. This does not seem to be a valid tag, (I could always use some RegEx to remove this), but is that 64 bit encoded string AFTER the "data:image/png;base64," substring a valid image? Can I say image.src=iVBORw...ASASDAS, and draw this back on the canvas?

I've looked at some related issues: Display canvas image from one canvas to another canvas using base64

But the solutions don't appear to be correct.


C
Chalist

Actually you don't have to create an image at all. drawImage() will accept a Canvas as well as an Image object.

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

Way faster than using an ImageData object or Image element.

Note that sourceCanvas can be a HTMLImageElement, HTMLVideoElement, or a HTMLCanvasElement. As mentioned by Dave in a comment below this answer, you cannot use a canvas drawing context as your source. If you have a canvas drawing context instead of the canvas element it was created from, there is a reference to the original canvas element on the context under context.canvas.

Here is a jsPerf to demonstrate why this is the only right way to clone a canvas: http://jsperf.com/copying-a-canvas-element


a small point which tripped me up: while you can draw a canvas (HTMLCanvasElement), you cannot draw a context (CanvasRenderingContext2D). Use myContext.canvas instead.
@Dave comment is a MUST READ... woud give +10 if possible ;). @Robert-Hurst must complement his answer with this comment since he doesn't specify from where source canvas comes from...
Could you please provide an example ?
@RogerGajraj Actually the canvas does not have to be visible. This is demonstrated there => jsfiddle.net/d36wwtvj
C
Community

@robert-hurst has a cleaner approach.

However, this solution may also be used, in places when you actually want to have a copy of Data Url after copying. For example, when you are building a website that uses lots of image/canvas operations.

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

I was needing to copy the contents of a canvas to use elsewhere - this was perfect as it generated ~80KB of data vs ~60MB using getImageData