iT邦幫忙

DAY 21
2

SVG 與 D3.js系列 第 21

D3.js Transition動態效果

  • 分享至 

  • xImage
  •  

完整範例:http://wcc723.github.io/d3js/2014/10/20/Ironman-30-days-21/

先前的資料,都是固定的,沒有任何變化,這次要介紹的是利用資料的轉變以及transition的效果。

Transition

這次的範例是之前提到那本書上的唷~。

D3.js的transition和CSS的transition很像,都是放在開始的地方,然後再加入一些時間,這樣就完成了,像下面這個範例:

d3.select('div')
.transition() //套用動態效果
.duration(250) //動態持續時間
.attr(/* do something */) 

如果和資料有關係,作法大致是相同的,再加入資料後,一樣加入.transition():

d3.select('div').data(dataset)
.transition() //套用動態效果
.duration(250) //動態持續時間
.attr(/* do something */) 

下面這一個範例中,只要點擊’Click Me’,就會產生出一組新的陣列並且套用入SVG,可以看到圓型以及左方、下方的軸線也會跟著轉場變化。

(完整範例:http://wcc723.github.io/d3js/2014/10/20/Ironman-30-days-21/)

var w = 600,h = 400,padding = 30;

var dataset = []; //產生空的陣列
var numDataPoints = 100; //最大點的數量是100
var xRange = Math.random() * 1000; 
var yRange = Math.random() * 1000; //隨機範圍最大值都是1000
for (var i = 0; i < numDataPoints; i++){
	var num1 = Math.floor(Math.random() * xRange);
	var num2 = Math.floor(Math.random() * yRange);
	dataset.push([num1,num2]) //運算出新的值,並加到dataset
}


var Xmax = d3.max(dataset, function(d){return d[0]}),
	Xmin = d3.min(dataset, function(d){return d[0]}),
	Ymax = d3.max(dataset, function(d){return d[1]}),
	Ymin = d3.min(dataset, function(d){return d[1]}); //計算最大值

var xScale = d3.scale.linear() //線性尺度
			.domain([0, Xmax]) //輸入值
			.range([padding , w - padding]) //輸出值
			.nice() //取最適合數值

var yScale = d3.scale.linear()
			.domain([0, Ymax])
			.range([ h - padding ,padding])
			.nice()




var svg = d3.select('.demo').append('svg').attr({'width': w,'height': h})

//裁切區域
svg.append('clipPath') //新增svg裁切區域
	.attr('id', 'chart-area') //定義id
	.append('rect')	//再增加一個矩型
	.attr({
		'x': padding,
		'y': padding,
		'width': w - padding * 2,
		'height': h - padding * 2	
	})
	
	svg.append('g')
		.attr('clip-path', 'url(#chart-area)') //套用裁切區域
		.selectAll('circle')
		.data(dataset).enter() //輸入資料
		.append('circle') //加入圓
		.attr({
			'cx': function(d){return xScale(d[0])}, //用x尺度算出cx位置
			'cy': function(d){return yScale(d[1])}, //用y尺度算出cy位置
			'r': '3px'
		});

//Axis
var xAxis = d3.svg.axis().scale(xScale) //用x尺度製作x軸線
	.orient("bottom") //標示位置
	.ticks(6) //尺度數量

var yAxis = d3.svg.axis().scale(yScale)
	.orient("left") //標示位置
	.ticks(6) //尺度數量

svg.append('g').attr('class', 'x axis') //定義尺度樣式
	.attr('transform', 'translate(0, '+ (h - padding) +')') //移動到下方
	.call(xAxis) //套用x軸線

svg.append('g').attr('class', 'y axis')
	.attr('transform', 'translate('+ (padding) +')', 0)
	.call(yAxis)


//轉場時的code,其實有許多是和原本相同
//如果有興趣的可以先全部讀完,再重新製作一次
d3.select('.btn').on('click', function(){ //每次點擊的時候
	dataset = []; //將陣列清空
	var xRange = Math.random() * 1000;
	var yRange = Math.random() * 1000;
	for (var i = 0; i < numDataPoints; i++){
		var num1 = Math.floor(Math.random() * xRange);
		var num2 = Math.floor(Math.random() * yRange);
		dataset.push([num1,num2])
	} //這段和前面一樣,YA

	var Xmax = d3.max(dataset, function(d){return d[0]}),
		Xmin = d3.min(dataset, function(d){return d[0]}),
		Ymax = d3.max(dataset, function(d){return d[1]}),
		Ymin = d3.min(dataset, function(d){return d[1]}); //一樣

	var xScale = d3.scale.linear() //由於尺度有重新計算,所以必須再跑一次
			.domain([0, Xmax])
			.range([padding , w - padding])
			.nice() //取整數

	var yScale = d3.scale.linear()
			.domain([0, Ymax])
			.range([ h - padding ,padding])
			.nice()

	svg.selectAll('circle').data(dataset)
		// .enter() //這不需要再加入
		// .append('circle') //這也不需要
		.transition() //套用動態效果
		.duration(250) //動態持續時間
		.each('start', function(){ //過場開始執行
			d3.select(this)
				.attr('fill', 'DeepPink')
				.attr('r', 2)
		})
		.transition() //套用動態效果
		.duration(1000) //第二段時間
		.attr({
			'cx': function(d){return xScale(d[0])},
			'cy': function(d){return yScale(d[1])},
			'r': '3px',
			'fill': 'black',
			'r': 5
		});

	// 更新Axis
	var xAxis = d3.svg.axis().scale(xScale)
		.orient("bottom") //標示位置
		.ticks(6) //尺度數量

	var yAxis = d3.svg.axis().scale(yScale)
		.orient("left") //標示位置
		.ticks(6) //尺度數量


	svg.select('.x.axis')
		.transition() //動態尺度
		.duration(1000)
		.call(xAxis);

	svg.select('.y.axis')
		.transition()
		.duration(1000)
		.call(yAxis);

});

如果圖表會產生變化,觀者可以感受到位移,可以感受到數值的變化,在繪製圖表的時候,適當的加入不僅可以更吸引人,而且閱讀性更佳(增加前後比較的資訊),但如果過度的效果,就會讓人眼花撩亂。


上一篇
D3.js 超粘的Voronoi Diagram繪圖
下一篇
D3.js 資料數量增減
系列文
SVG 與 D3.js30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言