Cómo copiar contenidos de un lienzo a otro lienzo localmente

129

Me gustaría copiar TODOS los contenidos de un lienzo y transferirlos a otro todo en el lado del cliente. Creo que usaría el método canvas.toDataURL()y context.drawImage()para implementar esto, pero me encuentro con algunos problemas.

Mi solución sería obtener Canvas.toDataURL()y almacenar esto en un objeto Image en Javascript, y luego usar el context.drawImage()método para volverlo a colocar.

Sin embargo, creo que el toDataURLmétodo devuelve una etiqueta codificada de 64 bits con "data:image/png;base64,"antepuesta. Esto no parece ser una etiqueta válida (siempre podría usar RegEx para eliminar esto), pero ¿es esa cadena codificada de 64 bits DESPUÉS de la "data:image/png;base64,"subcadena una imagen válida? ¿Puedo decir image.src=iVBORw...ASASDASy dibujar esto de nuevo en el lienzo?

He visto algunos problemas relacionados: Mostrar la imagen del lienzo de un lienzo a otro usando base64

Pero las soluciones no parecen ser correctas.

J Kao
fuente

Respuestas:

273

En realidad no tienes que crear una imagen en absoluto. drawImage()aceptará tanto un Canvascomo un Imageobjeto.

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

Mucho más rápido que usar un ImageDataobjeto o Imageelemento.

Tenga en cuenta que sourceCanvaspuede ser un HTMLImageElement , HTMLVideoElement o un HTMLCanvasElement . Como mencionó Dave en un comentario debajo de esta respuesta, no puede utilizar un contexto de dibujo de lienzo como fuente . Si tiene un contexto de dibujo de lienzo en lugar del elemento de lienzo desde el que se creó, hay una referencia al elemento de lienzo original en el contexto debajo context.canvas.

Aquí hay un jsPerf para demostrar por qué esta es la única forma correcta de clonar un lienzo: http://jsperf.com/copying-a-canvas-element

Robert Hurst
fuente
66
un pequeño punto que me hizo tropezar: aunque puedes dibujar un lienzo ( HTMLCanvasElement), no puedes dibujar un contexto ( CanvasRenderingContext2D). Usar en su myContext.canvaslugar.
Dave
3
El comentario de @Dave es DEBE LEER ... daría +10 si es posible;). @ Robert-Hurst debe complementar su respuesta con este comentario, ya que no especifica de dónde source canvasviene ...
Paulo Bueno
¿Podría por favor dar un ejemplo?
ShibinRagh
@RogerGajraj En realidad, el lienzo no tiene que ser visible. Esto se demuestra allí => jsfiddle.net/d36wwtvj
Robert Hurst
2

@ robert-hurst tiene un enfoque más limpio.

Sin embargo, esta solución también se puede usar, en lugares donde realmente desea tener una copia de la URL de datos después de la copia. Por ejemplo, cuando está creando un sitio web que utiliza muchas operaciones de imagen / lienzo.

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