I have a problem with Fabric.js.
When I'm trying to save fabric canvas like this:
var data = JSON.stringify(self.canvas.toJSON(['width', 'height']))
I get well serialized json with height and width properties.
But when I'm trying to deserialize it like that:
self.canvas.loadFromJSON(data, function () {
self.canvas.renderAll();
});
All objects init fine except height and width properties.
I saw deserialization example: http://jsfiddle.net/fmgXt/3/
If I add to json height and width properties its ignores with deserialization.
But if I set them into code - it also works well. Am I missing something?
At http://fabricjs.com/docs/fabric.StaticCanvas.html#loadFromJSON I didn't find any mentions for loadFromJSON about includedPropertiesNames list or something like that.
I've found a solution to get missing attributes at deserialization :
var object = JSON.parse(json); //use default json parser
canvas.loadFromJSON(json, function(){
canvas.width = object.width;
canvas.height = object.height;
});
This one made no luck for me.
I was able to make it working by setWidth and setHeight methods:
var object = JSON.parse(json);
canvas.loadFromJSON(json, function() {
canvas.setWidth(object.width);
canvas.setHeight(object.height);
canvas.renderAll.bind(canvas);
});
Related
I'm trying to add a group of items to the canvas, but want the group to be set at the bottom of the zorder stack when it gets added. Heres the code I'm trying to do:
//Reload the SVG now
var site_url = "/components/<?=$designObj->svg_filename?>";
fabric.loadSVGFromURL(site_url, function(objects, options) {
let componentObj = fabric.util.groupSVGElements(objects, options);
componentObj.setControlVisible(false);
componentObj.sendToBack(); //THIS DOESNT WORK - THROWS TYPE ERROR
componentObj.selectable = false;
componentObj.jdeation_comp_id = "base";
componentObj.jdeation_base_svg = "<?=$designObj->svg_filename?>";
canvas.add(componentObj).renderAll();
});
I get the following error when I call sendToBack():
TypeError: Cannot read property 'sendToBack' of undefined
Not sure I totally understand whats happening here, appears that sendToBack expects the type to be something other than group or something. Is there a better way to do this?
You can't .sendToBack() on an object that hasn't been added to the canvas yet. Use canvas.insertAt(componentObj, 0) instead of canvas.add(componentObj) to specify that the object should be added to the bottom of the stack.
I am trying to use the following suggested way to store canvas in the server:
Fabric.js - how to save canvas on server with custom attributes
But in my case, I am loading an image from a url like:
fabric.Image.fromURL(url, function(image) {
image.alt = product.skuId;
image.productClass = product.productClass;
canvas.add(image);
}, {
crossOrigin: "Annoymous"
});
But when I try to store the same in the db the newer attributes are not stored.
Is there a way to store custom attribute (or even "alt") in the DB?
Edit:
Created a fiddle with what I tried:
https://jsfiddle.net/anjhawar/dpyb7cf7/
When we press save the canvas is dumped in the local storage, but when we check the "objects" array we do not get the custom attributes i.e. "id" and "alt", as per the example.
Am I missing something?
Here my solution to store custom attribute (id).
fabric.Image.fromURL(link, function(img) {
img.set({
id : 'image_'+index,
width : canvas.width / 2,
height : canvas.height / 2
});
canvas.add(img).renderAll().setActiveObject(img);
});
For quick review here is a working code : http://jsfiddle.net/mullainathan/dpyb7cf7/1
I'm experimenting with Snap in order to use svg and need to be able to use the Maki icons defined in https://github.com/mapbox/maki.
My plan is to load the svg's I need, and then instantiate them for particular icons on a piece of Snap paper. But in order for this to work, I need to place the icon at a particular place on the paper, but I can't get translation to work. Neither one of the translation techniques below works; the code works as is, but always places the icon at the top left.
What am I missing? There's not enough documentation on Snap, and I don't know if the problem is with the way the Maki icon svg is defined, or my use of Snap.
var icon = Snap.load("maki/bicycle-24.svg", function(f) {
var g = f.select("g").clone();
// var g = f.select("#layer1").clone(); // also works
// g.transform("t120,120");
// var t = new Snap.Matrix();
// t.translate(120,120);
// g.transform(t);
paper.append(g);
});
The cloning needs to happen after the append, as when loading an svg in Snap its just a fragment.
So you will need to do something like...
paper.append(f);
var element = paper.select('#someId').clone();
element.transform( myTransform );
Thank you! That did the trick! And since Snap is so poorly documented, I'm going to insert the code here that allows a general solution.
// Base set from which markers are constructed
var iconSet = paper.group();
iconSet.attr({ class: 'hide' });
// Instantiations of icons
var markers = paper.g();
// Now, create SVG shape
var icon = Snap.load("maki/bicycle-24.svg", function(icon) {
// Add it to the icon set
iconSet.append(icon);
// Instantiate it and remove from main view
var element = paper.select('#svg4460'); // Copies it!
// var element = paper.select('#base'); // Selects something but doesn't work
// var element = paper.select('#layer1'); // Selects something but doesn't work
// var element = paper.select('#bicycle-24'); // Silent fail
element = element.clone();
element.remove();
// Clone this icon and move it
var t = new Snap.Matrix();
t.translate(10,120);
element.transform(t);
// Insert into main document view (markers)
markers.add(element);
});
Trying to follow along the tutorial here, but there isn't enough code presented to me to bridge the gaps.
Here is the fiddle I am working on to accomplish the same thing, with d3 loaded, however, the animation transitions are not concurrently happening, let alone at all, it is just changing the attributes, something I am already familiar with in SVG hard coding with JQuery selectors. So where am I going wrong, or missing the boat?
// example code doesn't work
var circle = svg.selectAll("circle");
circle.style("fill", "steelblue");
circle.attr("cy", 90);
circle.attr("r", 30);
// this does, but animations don't work
d3.selectAll('circle').style("fill", "steelblue");
d3.selectAll('circle').attr("cy", 90);
d3.selectAll('circle').attr("r", 30);
I am eventually trying to leverage the tweening of d3, but I cant get the basics off the ground. Thanks for you help in advance....
In the example code, svg is previously assigned to a d3 selection object:
var svg = d3.select("#chart-2").append("svg")
.attr("width", w)
.attr("height", h);
Therefore, you can use it to select the child elements, as in the original example.
Eg. your fiddle could be rewritten like so:
var svg = d3.select("#svg");
//svg is now a d3.selection object.
svg.on("click", function() {
var circle = svg.selectAll("circle");
circle.style("fill", "steelblue");
circle.attr("cy", 90);
circle.attr("r", 30);
});
Something to note about binding events using d3:
Within the anonymous function:
The event is bound to d3.event
The dom element - not the d3.selection object - is bound to this
If you pass an argument to the function, it will be bound to the data which is joined to the element.
Not really code, but should show what I mean:
var someD3Selection = d3.select("#someElement");
someD3Selection.on("click", function(boundData) {
d3.event.preventDefault(); // <-- here's the event
this; // <-- the actual dom element which is selected in someD3Selection
d3.select(this); // <-- same as someD3Selection.
});
Is this what you're looking for? The duration is optional but it's easier to see what's happening when it's a bit slower.
$('#svg').on('click', function() {
d3.selectAll('circle').style("fill", "grey").transition().duration(5000).style("fill", "steelblue").attr("cy", 90).attr("r", 30);
});
Good morning,everyone ,I have a problem that I want to pass an array of fabric json data to server, and load it back for after a while, since I have to load the details from canvas from multiple page pdf. It has to pass the canvas name as well.
problem here is if I use JSON.stringify(mycanvas);
it doesn't convert my customize attribute into json data. So I have to do something like inherit from the fabric canvas to extend the attribute.
I found some useful like to create custom text, custom image, I tried something similar to them, it just doesn't work. Please help me on this.
my code :
code to create such customize canvas
//////////////////////////////////////////////////////////////
create CustomCanvas class from Text class
fabric.CustomCanvas = fabric.util.createClass(fabric.Canvas, {
type: 'custom-canvas',
initialize: function(element, options) {
this.callSuper('initialize', element, options);
options && this.set('canvasname', options.canvasname);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'),
{canvasname: this.canvasname});
}
});
fabric.CustomText.fromObject = function(object) {
return new fabric.canvasname(object`enter code here`);
};
fabric.canvasname.async = false;`enter code here`
//////////////////////////////////////////////////////////////
//and to create a new customize canvas
var canvas = new fabric.CustomCanvas();
canvas.setBackgroundImage(src, function() {
canvas.renderAll();
});
canvas.canvasname=1111;
I will so appreciate it, if someone could help me on this.