這篇學習筆記是入門篇的最後一部分,將前幾篇的內容整合到一塊兒,繪製帶過渡效果的柱狀圖,此次先給你們看一下結果圖。
結果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); })
接下來會寫進階篇的學習筆記