上一回合写到《D3.js从入门到“放弃”指南》代码中D3结合了react全家桶来写可能有点副格略高。在这里回归原点,整理好D3使用过程中或者学习过程中遇到过的常见问题。这里主要是新手专区,把新手入门D3时常见的问题记录下来,D3高手不喜勿喷,当然也延续了自己的习惯,持续更新,把常见的问题记录下来好处就是平时可以当自己的Q&A顺手拿来使用,毕竟人的大脑有限。
我觉得得SVG适量图是必须的,为什么要学习SVG图呢?因为D3.js堪称SVG中的jQuery,稍稍熟悉点jQuery的话,会更容易上手D3,当然你如果想用D3输出Canvas图或者你牛逼哄哄的说老子就只用D3来玩Canvas怎么嘀也可以,但SVG图操作起来更加灵活,更加方便调试,在Chrome中调试SVG图更加直观。D3只是一个作图工具,你完全也可以手写SVG的XML代码来完成作图,如下面是一个手画简单柱状图:
- <svg class="chart" width="100%" height="120">
- <g transform="translate(0,0)">
- <rect width="0.7619047619047619em" height="19"></rect>
- <text x="0.6619047619047619em" y="10" dy=".35em">4</text>
- </g>
- <g transform="translate(0,20)">
- <rect width="1.5238095238095237em" height="19"></rect>
- <text x="1.4238095238095236em" y="10" dy=".35em">8</text>
- </g>
- <g transform="translate(0,40)">
- <rect width="2.857142857142857em" height="19"></rect>
- <text x="2.757142857142857em" y="10" dy=".35em">15</text>
- </g>
- <g transform="translate(0,60)">
- <rect width="3.0476190476190474em" height="19"></rect>
- <text x="2.9476190476190474em" y="10" dy=".35em">16</text>
- </g>
- <g transform="translate(0,80)">
- <rect width="4.380952380952381em" height="19"></rect>
- <text x="4.280952380952382em" y="10" dy=".35em">23</text>
- </g>
- <g transform="translate(0,100)">
- <rect width="8em" height="19"></rect>
- <text x="7.9em" y="10" dy=".35em">42</text>
- </g>
- </svg>
代码如下:
- // Update…
- var p4 = d3.select("#my_p_4")
- .selectAll("p") // 选择所有的P元素
- .data([4, 8, 15, 16, 23, 40]) // 给所有的P元素相应绑定数据(当然P元素有可能与数组元素个数不相等,则要转入下面的Enter和exit操作)
- .text(function (d) { return d; }); // 改变所有的P元素的text为相应的数组的值
- p4.enter().append("p") // 如果原有P节点元素小于数组的元素个数,则要给父节点append节点补足
- .text(function (d) { return d; });
- // Exit…
- p4.exit().remove(); // 如果原有P节点元素大于数组的元素个数,则要执行删除操作,以保证p节点元素个数与传入的data数组元素个数相当
用data是给所有的节点去绑定对应的data里面的数组元素值并一一匹配,而使用datum是给所有的节点绑定一样的数据值。
style设置权重其实比用CSS样式表来设置更高,代码如下:
- d3.select("#my_chart_2 rect").style("width", 20) // 同样设宽度用style生效
- .attr("width", 40); // 同样设宽度用attr权重没style高,会失效
一般可以这么操作,先定义变量暂存节点再单独写动画或者单独写append追加元毒操作,代码如下:
- var g = chart.append("g")
- .style('fill-opacity', 0);
- .transition()
- .duration(1000)
- .style('fill-opacity', 1); // 动画渐现
- /*g.selectAll("rect") // 绘画所有的矩形
- .data(data)
- .enter()
- .append("path")...
- */
如画饼图时,想加上缓动动画,代码如下:
- let arc = d3.arc() // 定义单个圆弧
- .innerRadius(0)
- .padAngle(0);
- let pie = d3.pie() // 定义饼图
- .sort(null)
- .value(function (d) { return d.population; });
- g.selectAll(".arc") // 画环图
- .data(pie(data)).enter().append("path").attr("cursor", "pointer").attr("class", "arc").attr('stroke',
- function(d) {
- return colors(d.data.age);
- }).style("fill",
- function(d) {
- return colors(d.data.age);
- }).each(function(d) { // 储存当前起始与终点的角度、并设为相等
- let tem = {...d,
- endAngle: d.startAngle
- };
- d.outerRadius = radius - 10;
- this._currentData = tem;
- }).transition().duration(100).delay(function(d, i) {
- return i * 100;
- }).attrTween("d",
- function(next) { // 动态设置d属性、生成缓动画
- var i = d3.interpolate(this._currentData, next);
- this._currentData = i(0); // 重设当前角度
- return function(t) {
- return arc(i(t));
- };
- });
或者单独定义好缓动函数,代码如下:
- g.selectAll(".arc") // 画环图
- .data(pie(data)).enter().append("path").each(function(d) { // 储存当前起始与终点的角度、并设为相等
- let tem = {...d,
- endAngle: d.startAngle
- };
- d.outerRadius = radius - 10;
- this._currentData = tem;
- }).on("mouseover", arcTween(radius + 50, 0)).on("mouseout", arcTween(radius - 10, 150)).attr("cursor", "pointer").attr("class", "arc").style("fill",
- function(d) {
- return colors(d.data.age);
- }).transition().duration(750).attrTween("d",
- function(next) { // 动态设置d属性、生成动画
- var i = d3.interpolate(this._currentData, next);
- this._currentData = i(0); // 重设当前角度
- return function(t) {
- return arc(i(t));
- };
- });
- function arcTween(outerRadius, delay) { // 设置缓动函数
- return function() {
- d3.select(this).transition().delay(delay).attrTween("d",
- function(d) {
- var i = d3.interpolate(d.outerRadius, outerRadius);
- return function(t) {
- d.outerRadius = i(t);
- return arc(d);
- };
- });
- };
- }
如果想要给柱图添加每条柱由左到右按顺序缓动弹出,代码如下:
- g.selectAll(".bar")// 画柱图
- .data(data)
- .enter().append("rect")
- .attr("x", function (d) { return x(d.letter); })
- .attr("y", height) // 控制动画由下而上
- .attr("width", x.bandwidth())
- .attr("height", 0) // 控制动画由下而上
- .transition()
- .duration(200)
- .ease(d3.easeBounceInOut) // 这里还有d3.easeLinear、d3.easeCubicOut等等多种效果,可自行查看API
- .delay(function (d, i) { return i * 200; })
- .attr("y", function (d) { return y(d.frequency); })
- .attr("height", function (d) { return height - y(d.frequency); });
当需要hover提示文本效果时,可以添加title,或者如果想要更加丰富的自定义效果可以使用开源的d3插件d3-tip,也可以自己写一个hover效果,实现起来的思想就是on('mouseover',callback)方式,代码如下:
- g.append("g")//
- .selectAll('rect')
- .data(data)
- .enter()
- .append('rect')
- //...
- .append('title') // 在后面添加title
- .text(function(d) { return d.name; });
在应用场景中,我们经常也会遇到要获得某元素的长宽等信息,实现代码如下:
- label.insert("rect", "text") // 生成背景白块
- .datum(function () { return this.nextSibling.getBBox(); }) // 这里在text前插入一个rect,并按照text的属性来设置长宽及坐标
- .attr('fill', '#fff')
- .attr("x", function (d) { return d.x; })
- .attr("y", function (d) { return d.y; })
- .attr("width", function (d) { return d.width; })
- .attr("height", function (d) { return d.height; });
当你实现不想花那么多时间去在作图时实现动画,可以考虑在SVG遮罩里面加动画来实现同样的效果,代码如下:
- chart.append("defs").append("clipPath") // 添加长方形方块,遮罩作用
- .attr("id", "clip")
- .append("rect")
- .attr("height", height)
- .attr("width", 0) // 用遮罩实现线动画
- .transition()
- .duration(1000)
- .attr("width", width);
- let serie = g.selectAll(".serie") // 生成两线条
- .data(series)
- .enter().append("g")
- .attr("class", "serie");
- serie.append("path") // 绘画线条
- .attr('clip-path', 'url(#clip)')
- .attr("class", "line")
- .style("stroke", function (d) { return z(d[0].key); })
- .attr('fill', 'none')
- .attr("d", line);
circle, line, rect, path, svg, g, defs, clipPath, text, title
一般来说,是两者配合使用,transform后再设置x, y坐标或者再结合dx, dy位置来设置节点的位置。
x轴, y轴, tick, legend, serie, brush, zoom, 散点, 线状图, 面积图, 柱状图, 饼图, 打包图, 弦图, 打包图, 雷达图, 力向导图, 树状图, 堆栈图, 组合线状/组合柱状图, 标签云图, geomap地图等
对应到D3API中必备的知识有:d3-selection(D3 选择器) d3-shape(D3 作图图形图) d3-transition(D3 过渡动画) d3-axis(D3 坐标) d3-scale(D3 比例尺生成工具)
来源: http://www.cnblogs.com/fastmover/p/7794519.html