D3.js核心函数之过渡

过渡是一种特殊类型的选择器,这种操作符的应用随时间平滑而不是瞬间变换

开始过渡

d3.transition([selection],[name]),创建动画过渡,等价于d3.select(document).transition()

transition.delay([delay]),指定过渡延迟,以毫秒为单位。如果延迟为常量,则所有的元素被赋予相同的延迟,如果延迟是一个函数,则这个函数的返回值将被用来为每个元素的延迟设置值。延迟总是相对一系列过渡中的第一个而言

transition.duration([duration]),指定每个元素的持续时间,单位为毫秒,默认持续时间为250毫秒

transition.ease([value[,arguments]]),指定过渡的缓动函数,cubic-in-out:默认缓动函数,慢入慢出;linear:普通的线性变化;circle:由慢到快的变换到最终状态;elastic:带有弹跳的到达最终状态;bounce:在最终状态处弹跳几次

过渡中的操作

内容

transition.attr(name,value),通过指定的name和value设置过渡属性的值

transition.attrTween(name,tween),name为过渡变化的属性名,tween是补间函数function(d,i,a),d是被绑定的数据,i是索引,a是指定属性的初始值,该函数返回的function(t),就是插值函数,t的范围是[0,1],0表示变化的起始,1表示变化的结束。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>补间动画</title>
		<script src="https://d3js.org/d3.v3.min.js"></script>
	</head>
	<body>
		<div class="box">
			<svg></svg>
		</div>
		<script type="text/javascript">
			var svg = d3.select("svg");
			var rect = svg.append("rect")
				.attr("fill", "yellow")
				.attr("x", 100)
				.attr("y", 100)
				.attr("width", 100)
				.attr("height", 30)
//初始值a等于100,当t等于0时,function(t)返回100。当t等于1时,function(t)返回400.此时,该过渡属性将width属性从100过渡到400,所用时间为2000ms(2s)
			var rectTran = rect.transition()
				.duration(2000)
				.attrTween("width", function(d, i, a) {
					return function(t) {
						return Number(a) + t * 300
					}
				})
		</script>
	</body>
</html>

transition.style(name,value[,priority]),通过指定的name和value设置过渡的css样式属性值,可选参数优先级priority可以指定为null或者字符串“important”(不带感叹号)

transition.styleTween(name,tween[,priority]),通过指定的补间函数指定名称过渡的css样式属性值,补间函数的用法和上面一样

transition.text(value),基于textContent属性,设置的文本内容将取代任何现有的子元素

transition.tween(name,factory),对指定的名称自定义一个补间函数,用法同上

transition.remove(),在过渡结束时删除选定的元素

控制

transition.each([type],listener),遍历每一个元素运行操作,如果不指定触发类型(type),则马上运行操作,当指定触发类型为start或者end时,会在过渡的开始或者结束时运行操作

transition.call(function[,arguments...]),调用指定的函数一次,call操作符和手动执行一个函数是一样的

transition.empty(),如果当前过渡是空的,则返回true;过渡是空的,是指它不包含任何非null元素

transition.node(),返回当前过渡的第一个非空元素,如果为空,则返回null

transition.size(),返回当前过渡元素的个数

定时器

d3.timer(function[,delay[,time]]),启动一个自定义动画计时器,重复的调用指定的函数,直到它返回true,计时器启动后没办法取消。功能相当于setTimeout,但内部用requestAnimationFrame实现,更高效

d3.flush(),立马运行当前没有延迟的计时,可用于处理闪屏问题

插值

插值器是一个函数,用来将值域[0,1]中参数值t映射为一种颜色、数字或者任意值

d3.interpolate(a,b),返回一个介于a和b之间的默认插值器。插值器的类型是基于后面一个值b的类型,使用以下算法:

  • 如果b是颜色类型,则返回interpolateRgb插值器
  • 如果b是字符串类型,则返回interpolateString插值器
  • 如果b是数组类型,则返回interpolateArray插值器
  • 如果b是对象类型,且不能强制转换为数字类型,则返回interpolateObject插值器,否则返回interpolateNumber插值器

interpolate(t),对在区间[0,1]中一个给定的参数t,返回相关的插入值。插值器通常结合比例尺一起使用,映射一个输入域到一个输出范围

d3.interpolateNumber(a,b),返回a,b两个数字之间的数字插值器。返回的插值器相当于:

function interpolate(t) {
  return a * (1 - t) + b * t;
}

 注意:当插值器用于生成一个字符串时,应该避免插入0或者从0返回插值器

d3.interpolateRound(a,b),返回a,b两个数字之间的数字插值器,其结果会四舍五入为整数

d3.interpolateString(a,b),返回一个a和b两个字符串之间的字符串插值器

d3.interpolateRgb(a,b),返回一个a和b两种颜色值之间的RGB颜色空间插值器,插值器的返回值是一个十六进制的RGB字符串

d3.interpolateHsl(a,b),返回一个a和b两种颜色值之间的Hsl颜色空间插值器,插值器的返回值是一个十六进制的RGB字符串

d3.interpolateLab(a,b),返回一个a和b两种颜色值之间的Lab颜色空间插值器,插值器的返回值是一个十六进制的RGB字符串

d3.interpolateHcl(a,b),返回一个a和b两种颜色值之间的Hcl颜色空间插值器,插值器的返回值是一个十六进制的RGB字符串

d3.interpolateArray(a,b),返回一个在两个数组a和b之间的数组插值器

d3.interpolateObject(a,b),返回一个于a和b两个对象之间的插值器

d3.interpolateTransform(a,b),返回一个由a和b表示的二维仿射变换的插值器

d3.interpolateZoom(a,b),在两个点之间平滑的缩放平移

d3.interpolates,内置的自定义插值器数组,由d3.interpolate所使用

下面是两个简单的过渡的例子

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>掉落的小球</title>
		<script src="https://d3js.org/d3.v3.min.js"></script>
		<style type="text/css">
			body{
				background: #000000;
			}
		</style>
	</head>
	<body>
		<div class="box"></div>
		<script type="text/javascript">
			let width = Math.max(960,innerWidth),
					height = Math.max(660,innerHeight);
			let svg = d3.select(".box").append("svg")
					.attr("width",width)
					.attr("height",height);
			let j = 0;
			function fun(){
				let dataset = [];
				for(let i=0;i<Math.random()*1000;i++){
					let item = {
						x:Math.floor(Math.random()*width),
						y:-40 
					}
					dataset.push(item)
				}
				let circle = svg.selectAll("circle")
						.data(dataset)
						.enter()
						.append("circle")
						.attr("cx",function(d){
							return d.x
						})
						.attr("cy",function(d){
							return d.y
						})
						.attr("r",18)
						.style("fill", d3.hsl((j = (j + 1) % 360), 1, .5))
						.transition()
						.duration(3000)
						.delay(function(d,i){
							return 200*i
						})
						.ease('bounce')
						.attr("transform",function(d){
							return "translate(0,"+(height-d.y-50)+")"
						})
						.transition()
						.duration(2000)
						.ease("linear")
						.attr("transform",function(d){
							return "translate("+(-d.x)+","+(height-d.y-50)+")"
						})
						.remove();
			}
			fun() 
			let timer = setInterval(fun,2000)
		</script>
	</body>
</html>
<!DOCTYPE html>
<meta charset="utf-8">
<title>霓虹</title>
<style>
	body {
		margin: 0;
		background: #222;
		min-width: 960px;
	}
	rect {
		fill: none;
		pointer-events: all;
	}
	circle {
		fill: none;
		stroke-width: 2.5px;
	}
</style>
<body>
	<script src="//d3js.org/d3.v3.min.js"></script>
	<script>
		var width = Math.max(960, innerWidth),
			height = Math.max(500, innerHeight);
		var i = 0;
		var svg = d3.select("body").append("svg")
			.attr("width", width)
			.attr("height", height);
		svg.append("rect")
			.attr("width", width)
			.attr("height", height)
			.on("ontouchstart" in document ? "touchmove" : "mousemove", particle);
		let times = []
		function particle() {
			var m = d3.mouse(this);
			times.push(m)
			let x1 = times[0][0]
			let y1 = times[0][1]
			let x2 = times[times.length - 1][0]
			let y2 = times[times.length - 1][1]
			let length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
			if (length > 80) {
				svg.insert("circle", "rect")
					.attr("cx", m[0])
					.attr("cy", m[1])
					.attr("r", 1e-6)
					.style("fill", d3.hsl((i = (i + 1) % 360), 1, .5))
					.style("opacity", 1)
					.transition()
					.duration(2000)
					.ease('bounce')
					.attr("r", 80)
					.style("opacity", 1e-6)
					.remove();
				times = []
			} else {
				return false
			}
			d3.event.preventDefault();
		}
	</script>

猜你喜欢

转载自blog.csdn.net/miao_yf/article/details/102477545