Is there a way to just generate an svg and get it as a string without actually drawing it? I thought about render svg to a hidden div and then reading the inner html, but is there a cleaner way?
-
Not sure what you're asking -- D3 creates the element and appends it to the DOM and there's no way around that. You can however create an element without attaching it to the DOM in pure Javascript. – Lars Kotthoff Jan 01 '14 at 21:38
-
I am using ExtJS, and want to render a sparkline inside a grid cell. I get the data in the reader before the grid is rendered. I am able to get around this issue by keeping the data and then rendering when the grid is drawn. This, however, is forcing me to move my rendering code from the reader where it should be to other files, and that's why I want to generate the sparkline as an svg to be appended as soon as the grid is drawn. – Isaac Jan 01 '14 at 21:46
-
Why do you get the data before rendering? It sounds as if you would want to keep data receiving/processing and rendering separate. – Lars Kotthoff Jan 01 '14 at 21:51
-
@LarsKotthoff, that's irrelevant. The question is whether d3.js can output SVG as a string, and if so, how. – Ian Jun 03 '16 at 14:46
3 Answers
I would think you could do this:
var svg = d3.select("body").append("svg")
svg = d3.select(svg).remove()
Append the svg to the body, but immediately remove it. This will, of course, give you the 'd3 selection' object, not a string.

- 1,568
- 1
- 15
- 28
You can create a whole other DOM tree in javascript using createDocumentFragment()
. This is commonly used to create a complex section of the document and then add it all to the page in one step, so the browser only has to re-calculate layout once.
I haven't tested it, but you should also be able to use .innerHTML()
to extract everything you've created as a string that can be saved to file. Answers to this SO Question suggest that you can't call innerHTML()
directly on the document fragment itself, so you would have to add a body element to the fragment, add your SVG to it, and then get the inner HTML from the body node.
One way to approach this problem is by checking how it would be done on the server side -- where there is no DOM.
As it turns out, the way to do this on the server side involves more or less the same "hack" used in the question. This is because d3 expects to work on a DOM; writing that DOM to HTML is really the only way to render it to a string.
Brief example:
var svg = window.d3.select('body')
.append('div').attr('class','container')
.append('svg'); // and lots of other stuff
//etc etc
svg.selectAll('.arc').doSomething('blah blah');
var svgAsString = d3.select('.container').html();

- 11,280
- 3
- 36
- 58