Any way to clone HTML5 canvas element with its content?
Actually the correct way to copy the canvas data is to pass the old canvas to the new blank canvas. Try this function.
function cloneCanvas(oldCanvas) {
//create a new canvas
var newCanvas = document.createElement('canvas');
var context = newCanvas.getContext('2d');
//set dimensions
newCanvas.width = oldCanvas.width;
newCanvas.height = oldCanvas.height;
//apply the old canvas to the new one
context.drawImage(oldCanvas, 0, 0);
//return the new canvas
return newCanvas;
}
Using getImageData is for pixel data access, not for copying canvases. Copying with it is very slow and hard on the browser. It should be avoided.
Possible to deep clone HTML5 canvas element with jQuery?
If you don't need to copy any attached event handlers (which, in general, I doubt is possible), I'd just use the currently accepted solution to Display canvas image from one canvas to another canvas using base64
//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);
Of course, you'd have to create the destination canvas first, so, before that, you'd have to:
var destinationCanvas = document.createElement('canvas');
destinationCanvas.width = sourceCanvas.width;
destinationCanvas.height = sourceCanvas.height;
Duplicating a canvas many times: clone the canvas or copy the image data?
Cloning a canvas will duplicate its dimensions and styling, but not its image data. You can copy the image data by calling drawImage
on the context. To paint the contents of originalCanvas
onto duplicateCanvas
, write:
duplicateCanvas.getContext('2d').drawImage(originalCanvas, 0, 0);
As a demonstration, the following snippet generates four canvases:
an original canvas with a small scene painted onto it
a copy made by calling
cloneNode
onlya copy made by calling
cloneNode
anddrawImage
a copy made by creating a new image and setting its source to the data URI
function message(s) { document.getElementById('message').innerHTML += s + '<br />';}
function timeIt(action, description, initializer) { var totalTime = 0, initializer = initializer || function () {}; initializer(); var startTime = performance.now(); action(); var elapsed = performance.now() - startTime; message('<span class="time"><span class="number">' + Math.round(elapsed * 1000) + ' μs</span></span> ' + description);}
function makeCanvas() { var canvas = document.createElement('canvas'), context = canvas.getContext('2d'); canvas.width = 100; canvas.height = 100; timeIt(function () { context.fillStyle = '#a63d3d'; context.fillRect(10, 10, 80, 40); // Paint a small scene. context.fillStyle = '#3b618c'; context.beginPath(); context.arc(60, 60, 25, 0, 2*Math.PI); context.closePath(); context.fill(); }, '(millionths of a second) to draw original scene', function () { context.clearRect(0, 0, canvas.width, canvas.height); }); return canvas;}
// copyCanvas returns a canvas containing the same image as the given canvas.function copyCanvas(original) { var copy; timeIt(function () { copy = original.cloneNode(); // Copy the canvas dimensions. copy.getContext('2d').drawImage(original, 0, 0); // Copy the image. }, 'to copy canvas with cloneNode and drawImage'); return copy;}
// imageFromStorage extracts the image data from a canvas, stores the image data// in a browser session, then retrieves the image data from the session and// makes a new image element out of it. We measure the total time to retrieve// the data and make the image.function imageFromStorage(original) { var image, dataURI = original.toDataURL(); timeIt(function () { image = document.createElement('img'); image.src = dataURI; }, 'to make image from a dataURI'); return image;}
function pageLoad() { var target = document.getElementById('canvases'), containers = {}, // We'll put the canvases inside divs. names = ['original', 'cloneNode', 'drawImage', 'dataURI']; for (var i = 0; i < names.length; ++i) { var name = names[i], // Use the name as an ID and a visible header. container = document.createElement('div'), header = document.createElement('div'); container.className = 'container'; header.className = 'header'; header.innerHTML = container.id = name; container.appendChild(header); target.appendChild(container); containers[name] = container; // The canvas container is ready. } var canvas = makeCanvas(); containers.original.appendChild(canvas); // Original canvas. containers.cloneNode.appendChild(canvas.cloneNode()); // cloneNode containers.drawImage.appendChild(copyCanvas(canvas)); // cloneNode + drawImage containers.dataURI.appendChild(imageFromStorage(canvas)); // localStorage}
pageLoad();
body { font-family: sans-serif;}.header { font-size: 18px;}.container { margin: 10px; display: inline-block;}canvas, img { border: 1px solid #eee;}#message { color: #666; font-size: 16px; line-height: 28px;}#message .time { display: inline-block; text-align: right; width: 100px;}#message .number { font-weight: bold; padding: 1px 3px; color: #222; background: #efedd4;}
<div id="canvases"></div>
<div id="message"></div>
Can you clone contents of an element into canvas?
You can use html2canvas to do it, you can checkout the demo at this JSFiddle.
html2canvas(document.getElementById('clone-me'), {
onrendered: function(canvas) {
var canvas1 = document.getElementById('canvas1');
var ctx = canvas1.getContext('2d');
ctx.drawImage(canvas, 0, 0);
}
});
jQuery clone() does not clone content of canvas
canvas "content" is not part of the DOM and can't be copied by DOM method. However, it's quite easy to call clonedCanvas.getContext('2d').drawImage(originalCanvas, 0,0)
which will draw the original canvas on the cloned one.
You could then try something like
// This will override the HTMLCanvas 'cloneNode' prototype(function(){ var ori = HTMLCanvasElement.prototype.cloneNode; HTMLCanvasElement.prototype.cloneNode = function(){ var copy = ori.apply(this, arguments); // don't do it for web-gl canvas if(this.getContext('2d')){ copy.getContext('2d').drawImage(this, 0,0); } return copy; }; })();
var original = document.querySelector('canvas');original.getContext('2d').fillRect(20, 20, 20, 20);
for(var i = 0; i<20; i++){ document.body.appendChild(original.cloneNode());}
<canvas></canvas>
Duplicate/Clone HTML5 canvas in realtime
thanks, here is my code
var canvas = new fabric.Canvas('canvas');
var canvas2 = new fabric.StaticCanvas('canvas2');
// doing some stuffs on 'canvas'
(...)
// clonage into canvas2
var c=document.getElementById("canvas2");
var ctx=c.getContext("2d");
var fabricHtmlCanvasElement = document.getElementById('canvas');
canvas.on('after:render', function(options) {
updateCanvas();
});
function updateCanvas(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(fabricHtmlCanvasElement,0,0);
}
it works perfectly thanks
How to Copy Contents of One Canvas to Another Canvas Locally
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
Clone items when clicked (Html5-canvas)
I can't test this since I don't have your context, but I think all you need to do is put all the code dealing with the Clone inside the event listener, something like what I've done below.
This way, each event will create a new copy of Clone, and the conflicts you were experiencing should disappear.
item = new lib.item104();
this.addChild(item);
item.x = 250;
item.y = 350;
item.scaleX = item.scaleY = 1;
item.addEventListener("click", itemPressed.bind(this));
function itemPressed(evt) {
var Clone;
Clone = new lib.anim104();
this.addChild(Clone);
Clone.x = 250;
Clone.y = 200;
Clone.scaleX = Clone.scaleY = 1.5;
Clone.addEventListener("pressmove", dragClone.bind(this));
}
function dragClone(evt) {
var p = this.globalToLocal(evt.stageX, evt.stageY);
evt.currentTarget.x = p.x;
evt.currentTarget.y = p.y;
}
Related Topics
Uncaught Error: Security_Err: Dom Exception 18 When I Try to Set a Cookie
How to Start Automatic Download of a File in Internet Explorer
Difference Between "Let" and "Var"
Why Is Document.Write Considered a "Bad Practice"
How to Loop Through or Enumerate a JavaScript Object
Compare Two Dates With JavaScript
Is Chrome'S JavaScript Console Lazy About Evaluating Objects
Object Comparison in JavaScript
Open a Url in a New Tab (And Not a New Window)
How to Access Previous Promise Results in a .Then() Chain
Disable Same Origin Policy in Chrome
Getelementbyid() Returns Null Even Though the Element Exists
JavaScript Onclick Function Is Called Immediately (Not When Clicked)
How to Download a File Without Using ≪A≫ Element With Download Attribute or a Server