Open raichu opened 11 years ago
You can do this manually at the moment and it should work, as far as I can tell. Marking as possible feature.
By the way, if we're talking about fully self-contained files, we'd need to at least also take care of fonts by embedding glyph definitions. Don't remember offhand, but I think SVG supports this.
You mean by editing toSVG() of Canvas? It seems to be supported indeed: http://www.w3.org/TR/SVG/fonts.html
So far, I found that the xlink:href part of an Image is written by getSvgSrc(), which is set to fabric.Image.prototype.getSrc, a function that simply returns this.getElement().src || this.getElement()._src;
. Is there really a way of getting a data URI out of this object?
As far as I have found, toDataURL is a function on the whole canvas, and is not defined for a single image, so the only way appears to be using a (hidden) ancillary canvas, paint the image on it, and run toDataURL on the ancillary canvas, and then destroy it.
Or am I missing something?
Edit: An alternative could be using using XMLHttpRequest + FileReader for remote files and FileReader for local files, and run readAsDataURL on load event, but this is asynchronous whereas toSVG is not.
Yeah, you're missing fabric.Image.prototype.toDataURL which does pretty much what you described in 2nd paragraph :)
kangax
On Tue, Apr 2, 2013 at 8:46 AM, raichu notifications@github.com wrote:
So far, I found that the xlink:href part of an Image is written by getSvgSrc(), which is set to fabric.Image.prototype.getSrc, a function that simply returns this.getElement().src || this.getElement()._src;. Is there really a way of getting a data URI out of this object?
As far as I have found, toDataURL is a function on the whole canvas, and is not defined for a single image, so the only way appears to be using a (hidden) ancillary canvas, paint the image on it, and run toDataURL on the ancillary canvas, and then destroy it.
Or am I missing something?
— Reply to this email directly or view it on GitHubhttps://github.com/kangax/fabric.js/issues/519#issuecomment-15758468 .
Yay :) One less thing to worry about. Thanks!
I just tried to change the function
getSrc: function() {
return this.getElement().src || this.getElement()._src;
}
to return this.toDataURL('png')
, but it doesn't work. I tried several other things such as this.callSuper('toDataURL', 'png')
or this.prototype.toDataURL('png')
, but none of them work. I'm sorry that I'm a bit new to Javascript and all that magic that emulates the true OOP; could you give me some pointers as to how and where I can use fabric.Image.prototype.toDataURL?
This is because toDataURL is asynchronous — http://fabricjs.com/docs/symbols/fabric.Object.html#toDataURL
Then it's no different than doing XMLHttpRequest + FileReader. So eventually, it can't be done? I don't see why what I describe in the 2nd paragraph has to be asynchronous though since it all could be done synchronously.
It's async because we're cloning an image before rendering it on "placeholder" canvas. Image is cloned so that original wouldn't be affected by transformations required to render it on a "placeholder" canvas. And cloning an image is an async process.
Now that I look at it, I think we might be able to remove clone step and just modify the same object, saving its original values (left, top, etc.) before rendering it onto "placeholder" canvas. I think that could work just as well (even be quicker) and would make toDataURL sync.
I'll tinker with it when I get a chance.
You'd be my savior :)
Is there any interest in adding this option today?
I remember we did something for it. Did you give a look at image toSVG implementation?
Yes - I saw the modifications, but these seem only to affect the situation, if I want to get out a single layer/object.
In my case, I have a canvas contiaining some (layered) objects. E.g. Rect, Image (img.src="..") and an Oval.
When exporting to SVG using canvas.toSVG
I want to embed the image as base64. So what I do is:
canvas.toSVG({suppressPreamble:true}, function(svg, a, b) { return svg; }
But here I get only the full svg-element containing the xlink:href
as src
.
Could it be, that I MUST overwrite the getSvgSrc
prototype to get the dataUrl or an image?
It seems this is everything required:
fabric.Image.prototype.getSvgSrc = function() {
return this.toDataURL();
}
canvas.toSVG({ suppressPreamble: true });
Well i remember we plan for this to be an option. But to do so, we need to convert the image at export time. Not a big deal, since if this is what the dev need, at some point he has to do it too.
I have not time to prioritize this over the other open things.
You can override the method as you pointed out, using the toDataUrl without any transformation ( or if the object is rotated, you will get a rotated dataUrl that is what you do NOT want )
OK - understood. Thanks for the explanation - so to keep the original image I have to convert the originalElement toDataURL if I intend to get the 'raw' (unmodified) image, right?
the Object.toDataUrl offers you the ability to skip transformations.
http://fabricjs.com/docs/fabric.Object.html#toDataURL
The withoutTransform option.
@asturur Bummer! I didn't see that in the docs - sorry! That's perfect! Grazie.
Currently, the image elements are exported with their "ordinary" URLs. Since SVG supports data URIs, it should be possible to embed these images and make the SVG output of the canvas self-contained.
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.