这篇学习笔记是入门篇的最后一部分,将前几篇的内容整合到一块儿,绘制带过渡效果的柱状图,此次先给你们看一下结果图。
结果app
先放结果图是想反馈一下在整合基础知识绘制完整柱状图遇到的几个问题:dom
!!!! 接下来将逐个解决上述出现的问题!!!!svg
Solution布局
(1)为了绘制时,图形四周留有空白区域,咱们首先设置一个padding值; var padding={top:40,bottom:40,left:40,right:40};//定义间隔 (2)咱们考虑在svg画布上进行绘制,采用以下的结构进行绘图: <svg> //将x轴包裹在一个g标签下 <g></g> //将y轴包裹在一个g标签下 <g></g> //将整个柱状图的矩形及文字包裹在一个g标签下 <g> //将柱形图的每一个矩形与它相应的值包裹在一个g标签下 <g> <rect> <text> </g> </g> </svg>
Solution
以前的几篇文章我都是经过transform变换实现了矩形的翻转,这篇文章介绍一个新的思路。
首先肯定一个矩形须要四要素(x,y,width,height),同时咱们须要注意,画布的坐标轴方向为水平向右和垂直向下。height是咱们数据可视化的展现部分,即数据的绑定部分,x,y肯定了绘制矩形的左上角坐标。
这里提供一个思路:
若是按照正常垂直向下的方向绘制矩形时,要求矩形的bottom处在同一水平线上,y+height==固定值;也就是数据(height)大的部分,咱们但愿矩形的绘制起始点(y)的值较小,数据小(height)的部分,咱们但愿矩形的绘制起始点(y)的值较大。
所以咱们能够经过定义比例尺完成这个功能,将dataset中大的数值,映射出range中小的数值。学习
//定义y方向比例尺 var yScale=d3.scaleLinear() .domain([0,d3.max(dataset)]) .range([height-padding.top-padding.bottom,0]); //定义y的值 .attr("y",function (d,i) { return yScale(d) }) //定义height .attr("height",function (d,i) { return height-padding.top-padding.bottom-yScale(d); }) 能够看出来‘y’+‘height’==height-padding.top-padding.bottom(这是一个固定的值)
Solution
在Problem1中已经解决的布局方案问题,咱们的方法是将矩形与文字包在一个g标签下,因此绘制文字与绘制矩形的方法相同,在<g>标签下添加<text>标签,同时须要设定:
(1)文字的显示位置:x,y
(2)文本信息:text
(3)文字位置的偏移值:dx,dy动画
graph.append("text") .style("fill","pink") .attr("x",function(d,i){ return xScale(i); }) .text(function (d) { return d }) .attr("y",function (d,i) { return yScale(d); })
Solution
为柱状图添加过渡效果,咱们须要调用如下API:spa
在为元素添加过渡效果时,初始状态,终止状态尤其重要,柱状图为例分析一下元素的两个状态:code
明确柱形图为每一个矩形添加过渡时,只有两个属性值须要改变,一个是y的值,一个是height的值;
起始状态:柱状图的起始状态很是好理解,就是矩形不显示的状态,即y值设定为前文提到的固定值,height设定为0;
终止状态:柱状图的终止状态应该是矩形元素和文字均可视化固定显示出来,即为正常绑定元素时设定的相关属性值。orm
//为矩形添加过渡效果 .attr("y",function (d) { var min=yScale.domain()[0]; return yScale(min); }) .attr("height",function(d,i){ return 0; }) .transition() .duration(2000) .delay(function(d,i){ return i*400; }) .ease(d3.easeBackOut) .attr("y",function (d,i) { return yScale(d) }) .attr("height",function (d,i) { return height-padding.top-padding.bottom-yScale(d); })
Solution
在开始学习坐标轴的时候,只实现了添加y轴,在此次完整柱状图实现中,尝试添加x轴却遇到了问题。在这个例子中咱们一共绑定了8个数据,那么如何让x轴的刻度均匀的显示在每一个矩形的下方呢?
在定义x轴的时候我用了ScaleBand()这个方法:blog
//在range返回等差数列 var xScale=d3.scaleBand() .domain(d3.range(dataset.length)) .rangeRound([0,dataset.length*(rectWidth+(rectPadding/2))]); var xAxis=d3.axisBottom(xScale) .ticks(5);
既然比例尺返回一个等差数列,因此咱们要求在柱状图区域,每一个矩形和空白间隔这个总体是相同的,因此个人实现是每一个矩形左右各是半个rectPadding。先设置x的值,而后width设置成矩形宽度减去半个间隔。(不理解的能够本身画一张图就能够了)
.attr("x",function (d,i) { return (i*rectWidth)+(i+1)*(rectPadding/2); }) .attr("width",rectWidth-rectPadding/2)
代码部分
import * as d3 from "d3"; var dataset = [45, 70, 12, 79, 4, 127, 33, 150]; var width = 600;//svg画布宽 var height = 600;//svg画布高 var rectWidth = 50;//每一个矩形的默认宽度 var rectPadding=10;//每一个矩形间的间隔 var padding={top:40,bottom:40,left:40,right:40};//定义间隔 //定义画布 var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height) .style("background-color", "yellow"); //定义矩形比例尺 var yScale=d3.scaleLinear() .domain([0,d3.max(dataset)]) .range([height-padding.top-padding.bottom,0]); var yAxis=d3.axisLeft(yScale) .ticks(5); svg.append("g") .attr("transform",`translate(${padding.top},${padding.left})`) .call(yAxis); var xScale=d3.scaleBand() .domain(d3.range(dataset.length)) .rangeRound([0,dataset.length*(rectWidth+(rectPadding/2))]); var xAxis=d3.axisBottom(xScale) .ticks(5); svg.append("g") .attr("transform",`translate(${padding.left},${height-padding.top})`) .call(xAxis); //定义矩形 var g=d3.selectAll("svg") .append("g") .attr("transform",`translate(${padding.top},${padding.left})`); var graph=g.selectAll("rect") .data(dataset) .enter() .append("g"); graph.append("rect") .style("fill","blue") .attr("x",function (d,i) { return (i*rectWidth)+(i+1)*(rectPadding/2); }) .attr("width",rectWidth-rectPadding/2) .attr("y",function (d) { var min=yScale.domain()[0]; return yScale(min); }) .attr("height",function(d,i){ return 0; }) .transition() .duration(2000) .delay(function(d,i){ return i*400; }) //.ease(d3.easeBackOut) .attr("y",function (d,i) { return yScale(d) }) .attr("height",function (d,i) { return height-padding.top-padding.bottom-yScale(d); }) graph.append("text") .style("fill", "pink") .attr("x", function (d, i) { return (i * rectWidth) + (i + 1) * (rectPadding / 2); }) .attr("dx", 10) .attr("y", function (d) { var min = d3.min(dataset); return yScale(min) }) .text(function (d) { return d }) .transition() .duration(2000) .delay(function (d, i) { return i * 400; }) .attr("y", function (d, i) { return yScale(d); })
接下来会写进阶篇的学习笔记