Reputation: 1318
I'm creating an app with Fabricjs.
I have to add an SVG file to the canvas and change the color every time a Minicolors input changes.
I first made the browser display the SVG images as SVG codes like so:
$('img[src$=".svg"]').each(function(){
var $img = $(this),
imgURL = $img.attr('src'),
attributes = $img.prop('attributes');
$.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = $(data).find('svg');
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Make sure that every attribute was copied
$.each(attributes, function() {
$svg.attr(this.name, this.value);
});
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
Then I loaded the SVG images from the DOM to the canvas when they get clicked on, like so:
$('#images').on('click', 'svg', function() {
var serializer = new XMLSerializer(),
svgStr = serializer.serializeToString(this);
fabric.loadSVGFromString(svgStr,function(objects, options) {
options.id = this.id;
var obj = fabric.util.groupSVGElements(objects, options);
canvas.add(obj);
obj.scaleToHeight(127) // Scales it down to some small size
.scaleToWidth(90)
.center() // Centers it (no s**t, Sherlock)
.setCoords();
canvas.setActiveObject(obj).renderAll();
});
});
Now for my next goal, how do I change the path color of the selected svg file? My main guess would be to follow these steps:
But I thought: "So I have to do all this every time a Minicolors input changes? Won't that be a performance issue later?"
Is there a better approach than this? Here's a JSFiddle that will get you started. Thanks.
Upvotes: 5
Views: 8144
Reputation: 9790
Answer by Nick Rameau is not working with the latest version of the fabricjs.
In my case, I'm working with fabricjs 3.5
.
In the latest version of the fabricjs, the paths
attribute has been removed. The paths
data has been added to the _objects
property.
This is how, I got it working for me.
var obj = this.canvas.itemObj;
var color = '#ff00ff';
if (obj && obj._objects) {
for (var i = 0; i < obj._objects.length; i++) {
obj._objects[i].set({
fill: color
});
}
}
Upvotes: 7
Reputation: 1318
When added to the canvas, the SVG object contains a property called "paths", which contains all the paths that build the image. So we do:
activeObject.paths.forEach(function(path) {path.fill = color});
But I wonder if it won't be a performance issue for huge SVG files (I won't get to that point, hopefully). Here's a working JSFiddle.
Upvotes: 3