How to generate svg client-side with d3 without attaching it to the DOM (using with React.js)
Asked Answered
S

2

9

I'm using React.js to build an app, which includes quite a few svg charts. I'm using d3 functions that help in chart creation, such as scales, but then using React to generate the svg elements. Here's a great writeup on the approach: http://10consulting.com/2014/02/19/d3-plus-reactjs-for-charting/

Part of why I'm going down this road was for performance - the first version of the app was too slow. It has a lot of elements and a lot of user-interactivity, all client-side. I'm trying to basically recreate the dc.js library in React.

It's a really fun approach and intuitive (more so than d3 alone IMO). Building axes is tedious though, and d3 does it so nicely. I would love d3 to just be able to output a string of svg elements that represent the axis (and maybe other elements) , and I feed it to React to include in the DOM.

I did see this SO question (How to make d3.js generate an svg without drawing it?) and the answer was to append it in the DOM and remove it, or create a DOM fragment. Those approaches go against the React approach and likely negate the performance benefits of React. I also saw jsdom and phantomjs solutions, which will not work in my case.

Can d3 generate svg without appending it to the DOM?

Squarerigged answered 30/6, 2014 at 22:48 Comment(4)
Hi. I've you found a solution so far ?Comptroller
@niahoo I know this was a long time ago, but I've built a plugin for D3 that allows you to render D3 -> React elements. D3 never mutates the DOM, the render function requires no state. github.com/Olical/d3-reactValediction
@niahoo, also worth noting. You can give D3 an element with jsdom and render things on the server side. So d3-react should give you isomorphic D3 github.com/Olical/d3-react/blob/…Valediction
@Valediction hey thanks :), I'll definitely look at your pluginComptroller
P
2

No. D3 by design operates directly on the DOM through its selections. To have it generate string representations instead without modifying the DOM, you would need to modify its source code (and it would be quite a significant modification).

Propylaeum answered 1/7, 2014 at 9:29 Comment(3)
Ok, thanks. The helper (non-DOM manipulating) functions are still very helpful for what I am doing.Squarerigged
You might get a boost by manipulating the DOM without it being on a page, i.e. without rendering to the page. dc is happy to work on a disconnected div. I don't know if this is enough of a boost though.Blase
Gordon, that's interesting. I've been working with dc.js for a while and didn't know about this. Do you of an example somewhere? (btw, thanks for all of the work on dc.js you've been doing lately)Squarerigged
W
3

@Lars is correct if you are using traditional means. However, this is definitely possible with 'jsdom'. This library can simulate the DOM and also allows for string input. Which means you could inject the root element into the fake DOM and get a new window element to manipulate. You could then use D3 without changing it's source and using is like normal.

This would allow for the generation of an SVG.

Wichman answered 27/12, 2014 at 23:26 Comment(2)
...have a look here: mango-is.com/blog/engineering/… , I guess this is what you have in mind?Hydro
Generating it on the server is one option. What I've settled on is doing is writing the SVG markup within React. That is fairly straightforward (see here: 10consulting.com/2014/02/19/d3-plus-reactjs-for-charting). Hard part is generating the crazy SVG path attributes. Fortunately d3 provides independent functions for those. For example d3.svg.area() and d3.svg.line(). Then I pass the generated area or line string into the path attribute. It's working well.Squarerigged
P
2

No. D3 by design operates directly on the DOM through its selections. To have it generate string representations instead without modifying the DOM, you would need to modify its source code (and it would be quite a significant modification).

Propylaeum answered 1/7, 2014 at 9:29 Comment(3)
Ok, thanks. The helper (non-DOM manipulating) functions are still very helpful for what I am doing.Squarerigged
You might get a boost by manipulating the DOM without it being on a page, i.e. without rendering to the page. dc is happy to work on a disconnected div. I don't know if this is enough of a boost though.Blase
Gordon, that's interesting. I've been working with dc.js for a while and didn't know about this. Do you of an example somewhere? (btw, thanks for all of the work on dc.js you've been doing lately)Squarerigged

© 2022 - 2024 — McMap. All rights reserved.