Jak lokalnie skopiować zawartość jednego płótna do innego płótna

129

Chciałbym skopiować CAŁĄ zawartość jednego płótna i przenieść je do innego, wszystko po stronie klienta. Pomyślałbym, że użyłbym metody canvas.toDataURL()i context.drawImage(), aby to zaimplementować, ale napotykam na kilka problemów.

Moim rozwiązaniem byłoby pobranie Canvas.toDataURL()i zapisanie tego w obiekcie Image w JavaScript, a następnie użycie context.drawImage()metody do umieszczenia go z powrotem.

Uważam jednak, że toDataURLmetoda zwraca tag zakodowany w 64 bitach z dołączonym "data:image/png;base64,"do niego tagiem . To nie wydaje się być prawidłowym znacznikiem (zawsze mógłbym użyć wyrażenia RegEx, aby go usunąć), ale czy ten 64-bitowy ciąg zakodowany za "data:image/png;base64,"podłańcuchem jest prawidłowym obrazem? Czy mogę powiedzieć image.src=iVBORw...ASASDASi narysować to z powrotem na płótnie?

Przyjrzałem się kilku pokrewnym problemom: Wyświetlaj obraz kanwy z jednego płótna na inne za pomocą base64

Ale rozwiązania nie wydają się być poprawne.

J Kao
źródło

Odpowiedzi:

273

Właściwie nie musisz w ogóle tworzyć obrazu. drawImage()przyjmie, Canvasjak również Imageobiekt.

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

O wiele szybciej niż używanie ImageDataobiektu lub Imageelementu.

Zwróć uwagę, że sourceCanvasmoże to być element HTMLImageElement , HTMLVideoElement lub HTMLCanvasElement . Jak wspomniał Dave w komentarzu pod tą odpowiedzią, nie możesz używać kontekstu rysunku na płótnie jako źródła . Jeśli zamiast elementu canvas, z którego został utworzony, masz kontekst rysunku na płótnie, w kontekście poniżej znajduje się odniesienie do oryginalnego elementu canvas context.canvas.

Oto jsPerf pokazujący, dlaczego jest to jedyny właściwy sposób klonowania płótna: http://jsperf.com/copying-a-canvas-element

Robert Hurst
źródło
66
mały punkt, który mnie zaskoczył: podczas gdy możesz narysować płótno ( HTMLCanvasElement), nie możesz narysować kontekstu ( CanvasRenderingContext2D). Użyj myContext.canvaszamiast tego.
Dave
3
@Dave komentarz jest MUSI CZYTAĆ ... woud dać +10, jeśli to możliwe;). @ Robert-Hurst musi uzupełnić swoją odpowiedź tym komentarzem, ponieważ nie określa skąd source canvaspochodzi ...
Paulo Bueno
Czy mógłbyś podać przykład?
ShibinRagh
@RogerGajraj Właściwie płótno nie musi być widoczne. Jest to zademonstrowane tutaj => jsfiddle.net/d36wwtvj
Robert Hurst
2

@ robert-hurst ma bardziej przejrzyste podejście.

Jednak z tego rozwiązania można skorzystać również w miejscach, w których faktycznie chcemy mieć kopię Data Url po skopiowaniu. Na przykład podczas tworzenia witryny internetowej, która wykorzystuje wiele operacji związanych z obrazem / płótnem.

    // 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;
vishwarajanand
źródło