8

我正在尝试在 d3.js 中构建一个矩形网格。

网格为 7 行(一周中的天数)和 24 列(一天中的小时数)。

以下代码仅绘制(行:列):day0:hour0,day1:hour1,day2:hour2,day3:hour3,day4:hour4,day5:hour5,day6:hour6,day7:hour7

问题:任何想法为什么以下代码不起作用?

/**
*   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;
}
4

1 回答 1

11

问题是您的数据绑定仅遍历数组的第一个维度 (0,1,2) 并且您试图使用它来遍历第二个维度 (0,0)(0,1)(0,2 ) 这导致 (0,0)(1,1)(2,2) 行为。

要获得您想要的结果,只需使用子选择。从您的行定义开始:

var row = chart.selectAll(".row") 
    .data(data) // each row will be bound to the array at data[i]
  .enter().append("div") 
    .attr("class", "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") 
    … 

您可以在http://bl.ocks.org/2605010看到一个完整源代码的工作示例。

于 2012-05-05T19:56:37.897 回答