最近初次接触D3.js
和nvd3.js
。尝试过更改一些例子,再结合官方的文档以及网上一些教程,对D3.js
学习越多越感受它的强大,也明白了为什么说D3.js
不单单是一个制作图表的库,而是一个直接操作DOM的强大的工具。
基于D3.js
的nvd3.js
提供了一些基础图表的接口,是一个可复用的D3图表库。支持饼图,柱状图,折线图等。好处是,比起直接使用D3.js
创建图表,需要写的代码会少一些。限制是,有些种类的图表目前nvd3.js
还不支持,比如雷达图等。
这次使用的是npm安装的zombiej-nvd3 ,版本1.8.2-3
。
官方API中给出的少数方法有的并不好用,甚至也没有描述如何调用,但是文档还是很大的帮助。
Nvd3 文档
Nvd3 Github Repo
另外,因为D3.js
是绘制的svg,所以也需要了解一下svg的结构。
nvd3柱状图制作
渐变色
svg的渐变色不能使用CSS中的linear-gradient
方式。而是要定义fill
属性。具体做法可以参考:svg教程:渐变 。
所以我们想只在图表的色板中添加一个渐变色是行不通的。或者使用接口 barColor
(详见文档)直接定义柱状图的颜色也是不行的。
首先我们需要像上面的svg教程中说到的那样,在svg元素中添加defs标签,然后自定义 linearGradient
。
//定义渐变色
if($(_chartCntr).find('#linear-gradient').length === 0){ //如果还没有定义过渐变色
var linearColor = d3.select(_chartCntr).append('defs')
.append('linearGradient')
.attr('id','linear-gradient')
.attr('x1','0%')
.attr('x2','0%')
.attr('y1','0%') //纵向渐变
.attr('y2','100%');
//定义渐变的起始和终止颜色
linearColor.append('stop')
.attr('offset',"0%")
.attr('stop-color','rgba(0,122,225,0.90)');
linearColor.append('stop')
.attr('offset',"100%")
.attr('stop-color','rgba(0,122,225,0.00)');
}
之后再按照教程设置柱状图的fill为 url(#linear-gradient)
就可以了(直接操作rect
节点,或者使用nvd3的颜色接口)。
圆角
设置rect标签的属性rx
或ry
就可以。
$(_chartCntr).find('.nv-bar').attr('rx', 10);
自定义tooltip
nvd3的图表都是有tooltip组件的。比如创建柱状图使用的 MultiBarChart
:
所以定制tooltip也很简单了。比如更改tooltip的内容:
//自定义tooltip
_chart.tooltip
.contentGenerator(function (data) {
var str = '<table><thead><tr><td><strong>' + data.value + '</strong></td></tr></thead>';
if(data.series.length !== 0) {
str = str + '<tbody><tr><td height ="10px"></td></tr>';
data.series.forEach(function(d){
str = str + '<tr></td><td class="key">' + d.key + ': </td><td class="value">' + d.value + '</td></tr>';
});
str = str + '</tbody>';
}
str = str + '</table>';
return str;
});
更多的操作可以查看官方文档中的Tooltip提供的方法。
自定义legend
默认的图例是靠右的。改为向左对齐,并设置margin:
//定义图例的位置等
_chart.legend
.rightAlign(false) //图例左对齐
.margin({"top":5,"bottom":20}); //图例上下margin
另外,尝试使用align('left')
不起作用,而且文档中对这个方法没有任何描述。所以试了rightAlign(false)
,然后就真的居左啦。
修改Y轴范围
使用MultiBarChart
创建的柱状图默认Y轴刻度并不是从0开始,而是从数据的最小值开始,所以最小值的柱子不会显示。在数据比较少的时候不太美观。
使用forceY方法不起作用。Github上有人提出这个问题,应该是还没有解决。forceY for the multiChart model #161 。
换了一个办法,使用yDomain
设置y轴的值域。使用方法:
nv.models.multiBarChart()
.yDomain([最小值, 最大值]) //设定y轴值域