7

我正在 d3 中构建我的第一个折线图:

http://jsfiddle.net/j94RZ/

我想知道如何利用比例或轴来绘制一个网格(可能是矩形),我可以在其中为网格的每个部分设置不同的背景颜色......所以我可以为每个部分交替颜色网格的单元格。我希望绘制网格并受图表轴的约束,然后在轴刻度的间距发生变化时进行调整(即轴的变化如下:http ://bl.ocks.org/mbostock/1667367 ) . 因此,如果我的图表有一个带有 4 个刻度的 x 轴和 7 个刻度的 y 轴,那么我的图表将有一个 7 块高和 4 块宽的背景网格。

我一直在尝试使用从零开始并以图形全宽结束的范围的想法,但我不知道我可以为该步骤使用什么值。有什么方法可以查询轴并返回有多少刻度?

var gridRange = d3.range(0, width, step?); 
4

2 回答 2

9

比您当前的解决方案更好的方法是scale.ticks()明确使用来获取刻度值。这样做的好处是,如果您出于某种原因更改刻度数,它仍然可以工作。

要获得交替网格图案而不是单个填充,您可以使用类似此代码的内容。

.attr("fill", function(d, i) {
    return (i % 2) == 1 ? "green" : "blue";
})

最后,要获得完整的网格模式,您可以按照建议使用显式循环,也可以使用嵌套选择。这里的想法是首先传入y刻度,为每个元素创建一个g元素,然后将x刻度传递给这些组中的每一个。在代码中,这看起来像这样。

svg.selectAll("g.grid")
   .data(y.ticks()).enter().append("g").attr("class", "grid")
   .selectAll("rect")
   .data(x.ticks()).enter().append("rect");

要设置位置,您可以像这样访问顶层和底层数据数组中的索引。

.attr("x", function(d, i) {
    return xScale(i);
})
.attr("y", function(d, i, j) {
    return yScale(j);
})

要设置x位置,您需要内部数组的索引(传递给g元素集),可以通过回调的第二个参数访问。对于外部数组,只需添加另一个参数(j此处)。

这就是它的全部。在这里完成 jsfiddle 。要动态更新此网格,您只需传入新的刻度值(从 获取scale.ticks()),与现有数据匹配,并以通常的方式处理进入/更新/退出选择。

如果您想不使用辅助刻度(即不使用.rangeBand()),您可以通过取刻度范围的范围并将其除以刻度数减 1 来计算矩形的宽度/高度。总而言之,这使得代码有点丑(主要是因为你需要的矩形比刻度少一个,因此需要减去/删除),但更通用一点。采用这种方法的 jsfiddle 在这里

于 2013-10-14T15:03:17.060 回答
1

因此,在上面的一些有用的评论之后,我已经接近了一个解决方案。使用 Ordinal 范围带可以让我靠近我想去的地方。

我通过使用轴上的刻度数作为输入域范围的基础来创建范围带:

  var xScale = d3.scale.ordinal()
            .domain(d3.range(10))
            .rangeRoundBands([0, width],0);


 var yScale = d3.scale.ordinal()
            .domain(d3.range(4))
            .rangeRoundBands([0, height],0);

然后我尝试像这样绘制矩形:

svg.selectAll("rect")
           .data(p)
           .enter()
           .append("rect")
           .attr("x", function(d, i) {
                return xScale(i);
           })
           .attr("y", function(d,i) {
                0
           })
           .attr("width", xScale.rangeBand())
           .attr("height", yScale.rangeBand())
                       .attr("fill", "green").
                       attr('stroke','red');

这让我得到了想要的效果,但只有一行深:

http://jsfiddle.net/Ny2FJ/2/

我想以某种方式为整个表格绘制绿色块(并且也不必硬编码序数刻度域中的刻度数)。然后我尝试像这样将范围带应用于 y 轴(知道这不会真正起作用)http://jsfiddle.net/Ny2FJ/3/

svg.selectAll("rect")
       .data(p)
       .enter()
       .append("rect")
       .attr("x", function(d, i) {
            return xScale(i);
       })
       .attr("y", function(d,i) {
            return yScale(i);
       })
       .attr("width", xScale.rangeBand())
       .attr("height", yScale.rangeBand())
                   .attr("fill", "green").
                   attr('stroke','red');

我能想到的唯一方法是引入一个 for 循环来为 y 轴的每个刻度运行这个小提琴http://jsfiddle.net/Ny2FJ/2/中的代码块。

于 2013-10-02T18:30:13.707 回答