D3.js 使用比例绘制栅格或矩形

D3.js 使用比例绘制栅格或矩形,d3.js,D3.js,我正在d3中构建我的第一个线条图: 我想知道如何利用比例或轴,让我画一个网格(大概是矩形),在那里我可以为网格的每个部分设置不同的背景颜色…这样我就可以为网格的每个单元格交替颜色。我希望绘制网格,并受图形的轴约束,然后在轴间距变化时进行调整(即轴变化如下:)。因此,如果我的图形的x轴有4个刻度,y轴有7个刻度,那么我的图形将有一个7块高,4块宽的背景网格 我一直在考虑使用一个从零开始到图形全宽结束的范围,但我不知道我可以用什么值来表示步长。有没有办法对查询轴进行排序并返回有多少个记号 var

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

我想知道如何利用比例或轴,让我画一个网格(大概是矩形),在那里我可以为网格的每个部分设置不同的背景颜色…这样我就可以为网格的每个单元格交替颜色。我希望绘制网格,并受图形的轴约束,然后在轴间距变化时进行调整(即轴变化如下:)。因此,如果我的图形的x轴有4个刻度,y轴有7个刻度,那么我的图形将有一个7块高,4块宽的背景网格

我一直在考虑使用一个从零开始到图形全宽结束的范围,但我不知道我可以用什么值来表示步长。有没有办法对查询轴进行排序并返回有多少个记号

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

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

我使用轴上的记号数作为输入域范围的基础,创建了范围标注栏:

  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');
这使我获得了所需的效果,但只有一行深:

我希望以某种方式为整个表绘制绿色块(也不必硬编码有序刻度域中的刻度数量)。然后我试着像这样将范围带应用于y轴(知道这实际上不起作用)


我能想到的唯一方法是引入一个for循环,在这个提琴中为y轴的每个记号运行代码块

一种比当前解决方案更好的方法是显式使用来获取刻度值。这样做的好处是,如果出于某种原因更改刻度的数量,它仍然可以工作

要获得交替网格模式而不是单个填充,可以使用以下代码

.attr("fill", function(d, i) {
    return (i % 2) == 1 ? "green" : "blue";
})
最后,要获得完整的网格模式,您可以按照建议使用显式循环,或者。这里的想法是首先传入
y
ticks,为每个组创建
g
元素,然后将
x
ticks传递给这些组中的每个组。在代码中,这看起来像这样

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);
})
要设置位置,您可以像这样访问顶级和底层数据数组中的索引

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。总的来说,这使得代码有点难看(主要是因为需要的矩形比记号少一个,因此需要减去/删除),但有点通用。采用这种方法的JSFIDLE是。

可能会有帮助。是的,这让我更接近。我现在有了网格线…我只需要以某种方式调整它,所以我画的不是直线而是矩形…也许也会有帮助。您可以使用控制勾号的数量,尽管只是大约。查看ordinal.rangeBands函数:好的,看起来很有趣。所以rangebands取一个低值和一个高值,并根据域的长度自动将其划分为偶数块。我的域长度应该是x轴上的刻度数。我可以看到如何使用范围带创建垂直带,宽度与我轴上每个刻度之间的空间一样宽,但不知道如何使范围带与y轴上的高度或刻度同时工作,以便我可以创建一个网格,其中网格正方形(矩形)与x轴和y轴匹配,但在我最初的实验中,仍然有很多硬编码的值让我宿醉。例如,从声明yAxis的位置删除刻度定义会破坏网格..并且在有序刻度域中仍然有硬编码的范围,因为刻度的数量将发生变化…我尝试在刻度域定义下移动有序刻度定义,然后使用axis.ticks()希望动态输出刻度的数量,但这不起作用这似乎是一种工作…但网格没有与轴对齐…我删除了你的附加刻度,只使用了原始刻度-这就是你要找的吗?代码有点难看,但在实践中应该可以很好地工作。好的,我将在答案中添加一些关于最新JSFIDLE的解释。我想你的意思是,而不是。scale.ticks生成域的刻度值,而axis.ticks允许您配置axis调用scale.ticks的方式。