Reputation: 9104
Suppose that I have data like this:
[{from: 3, to: 5}, {from: 1, to: 2}]
I'd like to generate the following SVG:
<svg width="100" height="100">
<g transform="translate(0,0)">
<rect x="0" width="5" height="5"></rect>
<rect x="10" width="5" height="5"></rect>
<rect x="20" width="5" height="5"></rect>
</g>
<g transform="translate(0,30)">
<rect x="0" width="5" height="5"></rect>
<rect x="10" width="5" height="5"></rect>
</g>
</svg>
Basically, for every data point, I have to generate to - from + 1
rectangles. This is how I started:
var width = 100;
var x = d3.scale.ordinal()
.domain(d3.range(10))
.rangeRoundBands([0, width]);
var svg = d3.select('svg').append('svg')
.attr('width', width)
.attr('height', 100);
var row = svg.selectAll('g')
.data(data)
.enter().append('g')
.attr('transform', function(d, i) { return 'translate(0,' + i * 30 + ')';});
Now, how do I generate multiple rects for every data point with the chain syntax?
I know that I could do it like this:
var rects = row.selectAll('rect')
.data(function(d) { return d3.range(d.to - d.from + 1);})
but I'd like to avoid creating useless arrays.
Upvotes: 3
Views: 339
Reputation: 5537
You could iterate in the append()
function and create your rects dynamically there:
var data = [{from: 3, to: 5}, {from: 1, to: 2}, {from: 4, to: 9}];
var width = 100;
var x = d3.scale.ordinal()
.domain(d3.range(10))
.rangeRoundBands([0, width]);
var svg = d3.select('div').append('svg')
.attr('width', width)
.attr('height', 100);
var row = svg.selectAll('g')
.data(data)
.enter().append(function(d) {
var rects = document.createElementNS('http://www.w3.org/2000/svg', 'g');
for (var i = d.from; i <= d.to; i++) {
var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('width', 5);
rect.setAttribute('height', 5);
rect.setAttribute('x', (i - d.from) * 10);
rects.appendChild(rect);
}
return rects;
})
.attr('transform', function(d, i) {
return 'translate(0,' + i * 30 + ')';
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div></div>
Upvotes: 2