Gain compatibility with react-primitives-svg.
@jbovenschen I'm new to react-pdf but maybe I can help with this since I need SVG support ASAP. What's the direction to resolve this? Would it be to add 'svg' to the switch in utils/image.js within the @react-pdf package and then use react-primitives-svg to actually the load the SVG file?
I'd recommend you look at https://github.com/devongovett/svgkit. It renders SVG files using PDFKit. I never quite finished it but it does pass a good portion of the SVG test suite. It should be possible to reuse a bunch of that code.
thanks @devongovett. I noticed that seems to be the direction pdf-make: https://github.com/bpampuch/pdfmake/issues/121.
thanks @jmjpro to show interest!
I recognize two different use cases here:
.svg file using the Image component (which I think is what you need right now)react-svg-primitives to build svg output inside the React code (which I think is what @jbovenschen thought when he created this issue)Would be cool to support both, of course.
@devongovett, I was looking at svgkit, but I didn't find how it can be used with pdfkit. The example I saw (I didn't run it though) exports the svg in a .png file (I think, correct me if I'm wrong). I guess there is a way of rendering the data stream inside the document instead of exporting it, but it would be great if you can explain a bit further how you see this working.
Another way would be using the pdfkit vector graphic API instead. Seems to me it can be possible, but don't how much effort would take and if covers all use cases.
@diegomura The parser is a streaming interface. Something like this should work:
import SVGParser from 'svgkit';
import fs from 'fs';
import PDFDocument from 'pdfkit';
let pdf = new PDFDocument;
pdf.pipe(fs.createWriteStream('out.pdf'));
fs.createReadStream('tiger.svg')
.pipe(new SVGParser)
.once('end', function () {
this.document.draw(pdf);
pdf.end();
});
That could work for use case (1) above. Creating SVG out of react components would require a bit more work, but basically just requires wrappers around the element classes in svgkit.
Awesome. I like this approach. Is very similar to the one we are following for almost everything, at least.
For (2) I agree we will need wrappers for all those elements (also present in the react-svg-primitives project, https://github.com/chengyin/react-primitives-svg/blob/master/src/core.web.js). Here, what we can do, is making the Svg wrapper render all the tree within it, and create a stream with the result and use that very same interface to draw it in the document. Just thinking out loud here. But I think is the way to go. @jmjpro would you like to be responsible of this module?
I'd say avoid the stream for (2). It's only a stream because it is parsing from a string using an XML parser. We don't need to parse XML because we have react elements. If instead we have the wrappers just construct the elements directly instead of the parser, then call draw on the root SVG node, it should work I think.
SVG wrapper node constructs svgkit SVGDocument node, and calls init.SVG wrapper is rendered, call draw on the SVGDocument.Awesome! If that's possible, I'd say we do it. I didn't check that svgkit inner elements were exported. Thanks @devongovett !
I have some pretty complicated SVGs using filters. The PDF is currently generated using PhantomJS and I'm looking for a more efficient mechanism.
Trying to digest all this now. Will get back to you guys...
Filters are hard because PDF doesn't really have a way to represent them. We'd basically have to rasterize the filtered elements and embed an image instead of vectors. svgkit doesn't implement filters for this reason.
I see that svgkit already has a devDependency on https://github.com/Automattic/node-canvas. Could node-canvas be used to rasterize the filtered elements? Since PDF is a static document, are there any disadvantages to rasterization for the purposes of PDF? Is it a performance issue?
In any event, I'm testing today whether or not I can reproduce the SVG filters as CSS filters to avoid the problem.
The issue with rasterizing is that it loses the scalable aspect of SVG, meaning that you cannot display it losslessly at any resolution anymore. Browsers will reapply the filter when you zoom in and out, but this cannot be done in PDF. Not only is this a problem for zooming in and out, but it's also an issue when displaying on different resolution displays, or high resolution printers for example.
Wrote a basic proof of concept for inline SVG support using svgkit. Code is pretty simple, see here, and here for a sample output. There is an SVG wrapper component, and from there it just traverses props.children to construct svgkit elements.
One issue I ran into is that it's not currently possible to create custom react-pdf components that do actual drawing using the pdfkit context directly. I don't think that SVG support should necessarily be part of react-pdf core, since svgkit isn't a small library. So I think it's important to come up with a way to extend react-pdf with custom components. For now I just added a hook to the View element to do some drawing, so you can pass a callback like this:
<View render={(doc) => doc.text('hello')} />
Not sure if this is the best way, or whether there should be some other way (e.g. a base class to inherit from or something). Perhaps even the core components could be written in the same way as whatever we come up with for custom components as well.
@devongovett Thanks for doing this man, looks really good and kinda like we intended to support svg in react-pdf.
What we could do is creating an other package named @react-pdf/svg which will register extra components like how you could add stuff to react-native which are not included in the core out of the box (see react-native-svg) as reference, so we would not create a huge package with stuff not everyone would want to use.
Guess using victory-charts would be a cool thing to test out if it is compatible with react-native and react-dom charts.
Will try to look into creating an extra package for svg inside react-pdf tomorrow.
Any updates on this?
@leontalbot Not from my end, sorry. Didn't have much time to cover this 馃槃
Any updates since last year?
@moritzmhmk nope sorry. There still things to do in other fronts and didn't had time. Adding this feature as help wanted if someone wants to grab it!
it would be really nice if someone can give a hand to this feature support
any news?
Not yet, sorry
Hi, any news here? It is very nice and desirable feature.
This looks promising
https://github.com/alafr/SVG-to-PDFKit
Hi ,
any update on SVG support in react-pdf ?
any updates?
@Ekta3012 @ghilman27 2.0 it's already deployed as beta in npm. You can try the lastest version if you really need svg. I'm doing my best to finally merge this version
Most helpful comment
Hi, any news here? It is very nice and desirable feature.