我正在d3中构建我的第一个折线图:
我想知道如何利用比例尺或轴允许我绘制网格(大概是矩形),我可以为网格的每个部分设置不同的背景颜色...所以我可以为每个部分交替颜色网格的单元格.我希望绘制网格并使其受到图形轴的约束,然后如果轴的间距变化也会适应(即轴的变化如下:http://bl.ocks.org/mbostock/1667367) .因此,如果我的图形具有4个刻度的x轴和7个刻度的y轴,则我的图形将具有7个块高和4个块宽的背景网格.
我一直在想使用一个从零开始并以图形的整个宽度结束的范围,但我不知道我可以用于该步骤的值.有没有办法对轴进行查询并返回有多少刻度?
var gridRange = d3.range(0, width, step?);
Run Code Online (Sandbox Code Playgroud)
比当前解决方案更好的方法是scale.ticks()明确使用获取刻度值.这样做的好处是,如果由于某种原因改变了滴答数,它仍然可以工作.
要获得交替网格图案而不是单个填充,您可以使用类似此代码的内容.
.attr("fill", function(d, i) {
return (i % 2) == 1 ? "green" : "blue";
})
Run Code Online (Sandbox Code Playgroud)
最后,要获得完整的网格模式,您可以使用您建议的显式循环或嵌套选择.这里的想法是首先传入y刻度线,g为每个刻度创建一个元素,然后将x刻度传递给这些组中的每一个.在代码中,这看起来像这样.
svg.selectAll("g.grid")
.data(y.ticks()).enter().append("g").attr("class", "grid")
.selectAll("rect")
.data(x.ticks()).enter().append("rect");
Run Code Online (Sandbox Code Playgroud)
要设置位置,您可以像这样访问顶层和底层数据数组中的索引.
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d, i, j) {
return yScale(j);
})
Run Code Online (Sandbox Code Playgroud)
要设置x位置,需要内部数组的索引(传递给g元素集),可以通过回调的第二个参数访问它.对于外部数组,只需添加另一个参数(j此处).
这就是它的全部内容.在这里完成jsfiddle .要动态更新此网格,您只需传入新的刻度值(从中获取scale.ticks()),与现有数据匹配,并以通常方式处理输入/更新/退出选择.
如果你想没有辅助刻度(即没有.rangeBand()),你可以通过取一个刻度范围的范围并除以刻度数减1来计算矩形的宽度/高度.总之,这使得代码有点丑陋(主要是因为你需要一个比刻度更少的矩形,因此需要减去/删除),但更一般.采用这种方法的jsfiddle就在这里.
因此,在上面的一些有用的评论之后,我已经接近解决方案了。使用序数范围带可以让我更接近我想去的地方。
我通过使用轴上的刻度数作为输入域范围的基础来创建范围带:
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);
Run Code Online (Sandbox Code Playgroud)
然后我尝试像这样绘制矩形:
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');
Run Code Online (Sandbox Code Playgroud)
这给了我想要的效果,但只有一行深:
我想以某种方式为整个表格绘制绿色块(并且也不必对序数刻度域中的刻度数进行硬编码)。然后我尝试将范围带应用到 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');
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一方法是引入一个 for 循环来运行这个小提琴http://jsfiddle.net/Ny2FJ/2/中的代码块,用于 y 轴的每个刻度。