I am trying to copy part of a fabricjs canvas to another canvas.I am not sure if fabric has a method suitable for doing it (please let me know if that's the case) and after some searching I decided to do it without using fabric. But the canvas was already created using fabricjs. new fabric.Canvas(). Now when I try to copy a part of this canvas using context.drawImage(), I get a TypeError. I tried replacing the canvas with a img or a canvas created without using fabric and that works. So, I am guessing I may have to use the fabric canvas object a bit differently.
If you want to copy a rectangular zone from the canvas in order to export it as an image you could use the following:
canvas.deactivateAll();
canvas.renderAll();
var ctx = canvas.getContext("2d");
var myImageData = ctx.getImageData(box.x, box.y, box.w, box.h);
var buffer = document.createElement('canvas');
var bufferCtx = buffer.getContext("2d");
buffer.width = box.w;
buffer.height = box.h;
bufferCtx.putImageData(myImageData, 0, 0);
window.open(buffer.toDataURL('image/png'));
Related
i have 2 canvases and i´m drawing on one of them.
Then i want to parse path from canvas one and paste in to canvas two.
How can i parse path from canvas one to JSON format in fabric.js ?
Thank you for all advices!
From the fabric.js docs the canvas can be serialized and deserialized:
var canvas1 = new fabric.Canvas('c');
var canvasJSON = JSON.stringify(canvas1);
var canvas2 = new fabric.Canvas();
canvas2.loadFromJSON(canvasJSON)
Up until now, I have set HTML canvas context the way in tutorials it is shown, like:
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
ctx.font = "15px calibri";
...
I was wondering whether it is possible to set the context of the canvas by passing in an object with the correct attributes to one of it's methods? For example:
var canvas = document.getElementById("canvas");
var context = {
font: "15px calibri",
...
);
canvas.setContext(context);
The reason for this is I am creating a custom canvas in angular. For example, my controller will get the <canvas> element. A method in a service will callback the context object to set for the canvas.
The custom canvas is to be converted to PNG and set as the icon for a Marker on Google Maps. The marker is added to the maps in the service:
addMarkerToMap: function(position, map, canvas) {
new google.maps.Marker({
position: position,
map: map,
icon: canvas.toDataURL("image/png")
});
}
So I am hoping to pass in the canvas element into this fucntion (with it's context already set) and just set it's PNG equivalent as the Marker icon.
EDIT:
I've now realised that other then just setting attributes (i.e. fillStyle), I am invoking the contexts methods (i.e. beginPath()).I think that this will make it much harder to accomplish what I am trying
Even though it looks like nonsence, after you mutate context of a canvas element, it is preserved:
const canvas1 = document.getElementById('myCanvas');
const ctx = canvas1.getContext('2d');
ctx.font = '15px Calibri';
const canvas2 = document.getElementById('myCanvas');
console.log(canvas2.getContext('2d').font); // -> "15px Calibri"
So, in you case, it is safe to rely on context at any moment in future after you pass reference to canvas element to addMarkerToMap function.
Based on this answer - and the spec as it says, you possibly cannot replace the canvas context with another, as "Every canvas has what is called a primary context".
If possible, you could create a canvas programmatically and then append it to HTML as a child (or even cloning & replacing the old one at cases - if not too many replacements happening).
You could for instance use jQuery to do something like:
// Just a new canvas, you could even clone the old one
var canvas1 = $('<canvas/>', {
id: 'canvas1',
height: 500,
width: 200,
font: '15 px'
});
document.body.appendChild(canvas1);
I have this
function doFirst(){
var x = document.getElementById('canvas');
var canvas = x.getContext('webgl') || x.getContext("experimental-webgl");
}
And I want to draw a image 'sheep.png' on the canvas. I use this but it is not working:
var pic = new Image();
pic.src = "images/sheep.png";
pic.addEventListener("load", function() { canvas.drawImage(pic,0,0,0)}, false);
drawImage is only for use with the 2D context, you can't use it in a webgl context.
In order to use it in webgl, you'll need to build a mesh with your image used as the texture.
If you're not familiar with webgl, you might want to look at three.js as an alternative that's easier to use.
drawImage()
takes only 3 arguments I guess.
See this demo.
and this reference
I have two canvases that are different sizes. My goal is copy the user's drawing from the main canvas to a second canvas as a scaled down version. So far the drawImage() and scale appear to be working, but the second canvas keeps the old version of the main drawing along with the new copy. I tried clearing it each time before calling drawImage(), but that doesn't appear to do anything. How can I copy just the current image to my secondary canvas each time the function runs?
$('#hand').dblclick(function(){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//var imageData = context.getImageData(0, 0, 100, 100);
var newCanvas = document.getElementById('scaledCanvas');
var destCtx = newCanvas.getContext('2d');
destCtx.clearRect(0, 0, newCanvas.width, newCanvas.height);
destCtx.scale(.5,.5);
destCtx.drawImage(canvas, 0, 0);
});
I can include more code if necessary. I also just realized that scale keeps getting called; this explains why the new copied image would get smaller each time as well, so that might be another problem.
It's quite simple actually, you're using what's called a transform (translate, rotate, or scale).
In order to use them "freshly" each time you must save and restore the canvas state each time.
$('#hand').dblclick(function(){
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//var imageData = context.getImageData(0, 0, 100, 100);
var newCanvas = document.getElementById('scaledCanvas');
var destCtx = newCanvas.getContext('2d');
destCtx.clearRect(0, 0, newCanvas.width, newCanvas.height);
//save the current state of this canvas' drawing mode
destCtx.save();
destCtx.scale(.5,.5);
destCtx.drawImage(canvas, 0, 0);
//restore destCtx to a 1,1 scale (and also 0,0 origin and 0 rotation)
destCtx.restore();
});
It's also important to note you can push several times before calling restore, in order to perform many cool geometric tricks using recursive functions etc...
Take a look at this explanation of states and transformations:
https://developer.mozilla.org/en-US/docs/HTML/Canvas/Tutorial/Transformations
Hope this helps you understand canvas transforms a bit better.
Is there any way to create a deep copy of a canvas element with all drawn 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.
You can call
context.getImageData(0, 0, context.canvas.width, context.canvas.height);
which will return an ImageData object. This has a property named data of type CanvasPixelArray which contains the rgb and transparency values of all the pixels. These values are not references to the canvas so can be changed without affecting the canvas.
If you also want a copy of the element, you could create a new canvas element and then copy all attributes to the new canvas element. After that you can use the
context.putImageData(imageData, 0, 0);
method to draw the ImageData object onto the new canvas element.
See this answer for more detail getPixel from HTML Canvas? on manipulating the pixels.
You might find this mozilla article useful as well https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Drawing_shapes