1 数轴简介
与比例尺相似,D3 的数轴实际上也是由你来定义参数的函数。但与比例尺不同的是,调用数轴函数并不会返回值,而是会生成数轴相关的可见元素,包括轴线、标签和刻度。
但要注意,数轴函数只适用于SVG 图形,因为它们生成的都是SVG 元素。同样,数轴是设计与定量比例尺(与序数比例尺相对)配合使用的。
2 设定数轴
使用d3.svg.axis() 可以创建通用的数轴函数:
var xAxis = d3.svg.axis();
要使用数轴,最起码要告诉它基于什么比例尺工作。在此,我们把绘制散点图时定义的xScale 传给它:
xAxis.scale(xScale);
还可以继续设置标签相对数轴显示在什么地方。默认位置是底部,也就是标签会出现在轴线下方。(虽然是默认值,但明确指定也不会引起异常。)水平数轴的位置可以在顶部也可以在底部。而垂直数轴则要么在左要么在右:
xAxis.orient("bottom");
当然,把这些方法连缀在一行会更简洁:
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
最后,要想实际生成数轴并把那些线条和标签插入到SVG 中,必须调用xAxis 函数。这一点与使用比例尺函数类似,即要先配置一番(设置参数),然后再通过调用将其付诸实用。
我想把这些代码放到脚本底部,以便在SVG 中的其他元素都生成之后再生成数轴,这样数轴就可以出现在“上面”了:
svg.append("g")
.call(xAxis);
的确看着有点不那么舒服。你可能会问,为什么调用数轴函数和调用比例尺函数看起来那么不一样呢?听我解释:
因为数轴函数实际上会在屏幕上绘制一些东西(通过把SVG 元素添加到DOM),所以我们需要指定在DOM 的什么地方插入这些新元素。这显然跟比例尺函数不一样,比例尺(比如xScale()),只是根据输入值来计算并返回值,主要是在其他函数里调用,不会影响DOM。
好,前面的代码首先引用了svg,即DOM 中的SVG 元素。然后,append() 在这个元素的末尾追加了一个新的g 元素。在SVG 标签内,g 元素就是一个分组。(group) 元素。分组元素是不可见的, 跟line、rect 和circle 不一样, 但它有两大用途:一是可以用来包含(或“组织”)其他元素,好让代码看起来简洁整齐;二是可以对整个分组应用变换,从而影响到该组中所有元素(line、rect 和circle)的视觉表现。关于变换,我们稍后就会介绍。
创建了新的g 元素后,直接在这个元素上面调用了call() 方法。那么call() 有什么用呢?
D3 的call() 函数会取得(比如刚才代码链中)传递过来的元素,然后再把它交给其他函数。对我们这例子而言,传递过来的元素就是新的分组元素g(虽然这个元素不是必需的,但鉴于数轴函数需要生成很多线条和数值,有了它就可以把所有元素都封装在一个分组对象内)。而call() 接着把g 交给了xAxis 函数,也就是要在g 元素里面生成数轴。
假设你喜欢把代码写得让人不容易看懂,那么可以把前面的两段合成下面这一段:
svg.append("g")
.call(d3.svg.axis()
.scale(xScale)
.orient("bottom"));
瞧,一行代码就定义并调用了数轴函数。不过,考虑到我们大脑的喜好,还是像前面那样先定义函数,然后再调用它更好理解。
无论如何,下图就是现在的结果
3 修整数轴
严格来讲,那确实是一个数轴。但从实用角度看,这家伙既不好看,也不中用。接下来看看怎么给它打扮一下。先给新创建的g 元素指定一个axis 类吧,这样好给它添加CSS 样式:
svg.append("g")
.attr("class", "axis") // 指定"axis" 类
.call(xAxis);
然后,在
中的