Search code examples
jqueryd3.jsappenddocumentfragment

How to append nested svg elements to dom with d3.js


I have looked around and it seems like this may not be possible but it would be amazing if you could use the selection capabilities of d3 to grab a whole chunk of svg markup and use it as the schema for a structure that you wanted to replicate several times. Example:

<g class='nice'>
<g class="slice">
    <path fill="#3182bd" d="M1.836909530733566e-15,-30A30,30 0 0,1 25.98076211353316,-14.999999999999995L0,0Z"></path>
    <text transform="translate(10.500000000000002,-18.186533479473212)" text-anchor="middle">bla2</text>
</g>
<g class="slice">
    <path fill="#6baed6" d="M25.98076211353316,-14.999999999999995A30,30 0 0,1 25.980762113533153,15.000000000000007L0,0Z"></path>
    <text transform="translate(21,4.6629367034256575e-15)" text-anchor="middle">bla</text>
</g>

would be much easier to just pop into your current enter loop rather than having to add the fill and d and transform attrs for each element like

.append('path')
.attr('transform', 'M25.98076211353316,-14.999999999999995A30,30 0 0,1 25.980762113533153,15.000000000000007L0,0Z')
.attr(.... etc etc etc

I guess I am wishing that d3 was more like jquery. Anyone have an idea of how you could do that?


Solution

  • When using d3 .html() method, watch out for innerHTML support for SVG elements (not supported in safari, IE).

    You can, however, use innerSVG polyfill for same effect. See https://code.google.com/p/innersvg/ for details. It just works.

    Use it like this:

    D3Selection.append("g").node().innerSVG = "<circle class=...";
    

    Better approach could be to introduce method for nesting desired structure on provided d3 selected element and use that. Eg.:

    function appendCircles(group) { 
        group.append("circle").attr("class", "circle1");
        group.append("circle").attr("class", "circle2");
    }