I'm trying to build a grid of rectangles in d3.js.
The grid is 7 rows (days in a week), and 24 columns (hours in a day).
The following code only draws (row:column): day0:hour0, day1:hour1, day2:hour2, day3:hour3, day4:hour4, day5:hour5, day6:hour6, day7:hour7
Question: Any ideas why the following code wouldn't work?
/**
* calendarWeekHour Setup a week-hour grid:
* 7 Rows (days), 24 Columns (hours)
* @param id div id tag starting with #
* @param width width of the grid in pixels
* @param height height of the grid in pixels
* @param square true/false if you want the height to
* match the (calculated first) width
*/
function calendarWeekHour(id, width, height, square)
{
var calData = randomData(width, height, square);
var grid = d3.select(id).append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "chart");
grid.selectAll("rect")
.data(calData)
.enter().append("svg:rect")
.attr("x", function(d, i) { return d[i].x; })
.attr("y", function(d, i) { return d[i].y; })
.attr("width", function(d, i) { return d[i].width; })
.attr("height", function(d, i) { return d[i].height; })
.on('mouseover', function() {
d3.select(this)
.style('fill', '#0F0');
})
.on('mouseout', function() {
d3.select(this)
.style('fill', '#FFF');
})
.on('click', function() {
console.log(d3.select(this));
})
.style("fill", '#FFF')
.style("stroke", '#555');
}
////////////////////////////////////////////////////////////////////////
/**
* randomData() returns an array: [
[{id:value, ...}],
[{id:value, ...}],
[...],...,
];
~ [
[hour1, hour2, hour3, ...],
[hour1, hour2, hour3, ...]
]
*/
function randomData(gridWidth, gridHeight, square)
{
var data = new Array();
var gridItemWidth = gridWidth / 24;
var gridItemHeight = (square) ? gridItemWidth : gridHeight / 7;
var startX = gridItemWidth / 2;
var startY = gridItemHeight / 2;
var stepX = gridItemWidth;
var stepY = gridItemHeight;
var xpos = startX;
var ypos = startY;
var newValue = 0;
var count = 0;
for (var index_a = 0; index_a < 7; index_a++)
{
data.push(new Array());
for (var index_b = 0; index_b < 24; index_b++)
{
newValue = Math.round(Math.random() * (100 - 1) + 1);
data[index_a].push({
time: index_b,
value: newValue,
width: gridItemWidth,
height: gridItemHeight,
x: xpos,
y: ypos,
count: count
});
xpos += stepX;
count += 1;
}
xpos = startX;
ypos += stepY;
}
return data;
}
The problem is that your databinding is only iterating through the first dimension of the array (0,1,2) and you are trying to use it to iterate through the second dimension (0,0)(0,1)(0,2) which is leading to the (0,0)(1,1)(2,2) behavior.
To get the results you want, just use a subselect. Start with your row definition:
var row = chart.selectAll(".row")
.data(data) // each row will be bound to the array at data[i]
.enter().append("div")
.attr("class", "row")
…
Then use the identity function (as the data property) to dereference the cells for each row:
var cell = row.selectAll(".cell")
.data(function(d) { return d; }) // then iterate through data[i] for each cell
.enter().append("div")
.attr("class", "cell")
…
You can see a working example with full source at http://bl.ocks.org/2605010.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With