Reputation: 3806
Using d3 what is the best way to append a whole series of svg elements to a particular selection. For example...First i append a rect.
tb.append("svg:rect")
.attr("width", "18")
.attr("height", "18")
.attr("y", "9")
.attr("x", (i * 20) + 5)
.attr("rx", "4")
.attr("ry", "4");
Now dependent on options i want to append an icon. The icon could be a series of paths or rects or polygons. but is dynamic and based on options. So i would like to do something like:
tb.append('<path d="M9.826,4.703C8.863,3.057,7.014,2.032,5.001,2.032c-2.012,0-3.861,1.024-4.829,2.671L0,5l0.173,0.299C1.141,6.944,2.99,7.968,5.001,7.968c2.012,0,3.862-1.023,4.825-2.669L10,5L9.826,4.703z M8.451,5.189C7.764,6.235,6.441,6.888,5,6.888c-1.438,0-2.762-0.652-3.453-1.698l-0.124-0.19l0.124-0.188C2.239,3.764,3.562,3.112,5,3.112c1.441,0,2.763,0.651,3.451,1.698l0.125,0.188L8.451,5.189z"/><circle cx="4.999" cy="5" r="1.905"/>');
or
tb.append('<polygon points="8.272,0 5.8,4.166 9,4.166 1.615,10 3.461,5 1,5 3.743,0.007"/>');
But i don't know the element type or varying attributes as it is fed in. Is there a pattern to just insert an entire element as a string? or a better pattern?
Upvotes: 0
Views: 1957
Reputation: 25157
EDIT: I just typed up the answer below, but, upon re-reading your question, I'm not sure if, by "dynamic and based on options" you actually meant that the icon type is dependent on the data. Let me know if I misinterpreted, and I'll delete this answer....
Let's say you have dataArray
which is an array of objects making up your data.
And then you have:
var selection = d3.selectAll('.icon').data(dataArray)
Then, what it sounds like you're asking is to conditionally create elements of, say, either <rect>
or <circle>
, depending on your data. Ideally, what you would want –– BUT d3 won't let you do it –– is:
selection.enter()
.append(function(d) { // <-- doesn't work :(
return d.type == 'round' ? 'circle' : 'rect';
})
.attr('class', 'icon');
I.e, the .append()
method doesn't accept a function. So, instead, what you could do is this:
selection.enter()
.append('g')
.each(function(d, i) {
var g = d3.select(this); // That's the svg:g we've just created
if(d.type == 'round')
g.append('circle')
else
g.append('rect')
})
.attr('class', 'icon');
What you get in the DOM is something like this (depending of course on what's inside dataArray
):
<svg>
<g class="icon">
<circle>
</g>
<g class="icon">
<rect>
</g>
<g class="icon">
<rect>
</g>
<g class="icon">
<circle>
</g>
Upvotes: 6