一、需求
制定數據結構,用餅圖可視化數據。
1.渲染餅圖并帶有順時針旋轉展示效果
2.鼠標經過每一項時,該項半徑變大,離開時恢復
3.鼠標經過在鼠標位置出現tip 框(我用backbone實現,不作為講解重點)
4.圖例legend
二、分析需求
1.需要的數據:
{ type 圖表類型 title 圖表名稱 legend 圖例數據 tooltip 提示 durationTime 動畫持續時間 series 圖表數據 }
三、數據結構
** 所有圖形的數據結構都暫定為如下格式,對于餅圖xAxis、yAxis則為null**
'pie':{
type:'pie',
title:{
text:'this is a demo' //圖標名稱
},
legend:{
orient:'vertical',//horizontal||vertical 橫排或者豎排
x:300, //在svg中的位置
y:100,
width:16,
height:16,
padding:5,
// data:['直接訪問','郵件銷售','聯盟廣告','視頻廣告','搜索引擎']
},
tooltip:{
dataLabels:{
color:'#fff',
bgColor:'red'
}
},
durationTime:100, //動畫的持續時間
xAxis:null, //x軸數據
yAxis:null, //y軸數據
series:{
title:'數據來源',
radius:{
outerRadius:70,
innerRadius:0
},
center:{
x:100,
y:100
},
data:[
{value:10,data:'直接訪問'},
{value:20,data:'郵件銷售'},
{value:30,data:'聯盟廣告'},
{value:30,data:'視頻廣告'},
{value:30,data:'搜索引擎'}
]
}
}
四、分解
1.渲染餅圖
2.添加動畫
3.增加hover效果
3.渲染legend
五、實現
1.渲染餅圖
在渲染餅圖時我們需要做:
1.1、用d3提供的 layout將數據轉換為pie所需要的數據格式
this._pie = d3.layout.pie()
.sort()
.value(function(d){
return d.value
})
.startAngle()
.endAngle()
sort:和js 中的sort方法一直,接受一個排序函數。不一樣之處為它的排序對每一項數據的startAngle和endAngle起作用。
value 是用來劃分每一項在圓環上所占的比例
startAngle和endAngle分別表示整個餅圖的起始弧度和終止弧度
1.2、設置arc
this._arc = d3.svg.arc()
.innerRadius()
.outerRadius()
.padRadius()
.startAngle()
.endAngle()
我們可以想想一下:
但我們畫圓環時,是不是需要用svg 的path實現,path標簽的d屬性時不時會很難,d3.svg.arc()可以根據pie轉換后的數據計算出d的取值。
1.3、設置顏色構造器
this._color = d3.scale.category20()
1.4、繪制
d3.svg.append('g')
.append('path)
.attr({
d:function(d,i){
return self._arc(d)
}
color:function(d,i){
return self._color(i)
}
})
上面演示了 arc 和color的用法
1.5、動畫
.transition()
.delay()
.duration()
.ease('linear')
.attrTween('d',function(d,i){
var fn = d3.interpolateObject({
endAngle:d.startAngle
},d)
return function(t){
return self._arc(fn(t))
}
})
為了制作連貫的動畫,需要在startAngle和endAngle中間插入一些過度值,d3提供了interpolateObject(a,b)方法,根據a,b在a,b之間插入中間值。
1.6、legend
legend制作的難點在于 如果將所有的圖例都水平排列,如果確定每一個圖例的大小,由于svg 在繪制每一個元素時都是以左上角為起始,需要translate,因此我們需要獲得每一個圖例的寬度。
svg中的g類似與div 它的寬高為其內容的寬高,但是不能夠用$(div).width()獲得,d3提供了這樣的方法。
d3.select('g').getBBox().width