《js动画效果》之缓冲动画

学习资源来自慕课网《js动画效果》:http://www.imooc.com/learn/167

这里的缓冲动画指的是非匀速运动的动画,这里以速度动画原型为基础修改代码:

<!DOCTYPE HTML>
<html>
	<head>
		<meta charset="utf-8">
		<style type="text/css">
		*{
			padding:0;
			margin:0;
		}
		#box{
			width:200px;
			height:200px;
			background:red;
			position:relative;  /*物体初始必须要有此参数,否则不能实现物体的移动*/
			left:-200px;
			top:0;
		}
		#box span{
			width:20px;
			height:45px;
			background:green;
			position:absolute;
			left:200px;
			top:75px;
			color:#fff;
			text-align:center;
			padding-top:10px;
			cursor:pointer;
		}
		</style>
		<script type="text/javascript">
		window.onload = function(){
			var divEle = document.getElementById("box");
			divEle.onmouseover = function(){
				playBox3(0);  //更精简的函数
			};
			divEle.onmouseout = function(){
				playBox3(-200); //更精简的函数
			}

		}

		//定义定时器初始化为null
		var timer = null;


		//简化参数个数的函数
		function playBox3(target){
			//先清除之前的定时器,避免开多个定时器造成bug
			clearInterval(timer);
			var divEle = document.getElementById("box");
			var speed = 0;

			//简化传参个数,为移动速度赋值
			/*if(divEle.offsetLeft > target){
				speed = -10;
			}else{
				speed = 10;
			}*/

			timer = setInterval(function(){

				//非匀速运动的速度计算
				var speed = (target - divEle.offsetLeft)/10;

				//速度为正时Math.ceil向上取整,速度为负值Math.floor向下取整
				//这里必须分情况取整,不然物体运动停止时达不到目标值target
				speed = speed > 0?Math.ceil(speed):Math.floor(speed);
				
				if(divEle.offsetLeft == target){ //面板全部移出/移入时,清空定时器,停止运动
					clearInterval(timer);
				}else{
					divEle.style.left = divEle.offsetLeft + speed +"px";
				}
				console.log(divEle.offsetLeft);
			},50); //每个50ms物体匀速运动 speed + "px"
		}

		</script>
	</head>
	<body>
		<div id="box"><span id="share">分享</span></div>
	</body>
</html>

分析:

缓冲动画实现的关键点是speed的计算,且注意对于正负值得处理,速度为正时Math.ceil向上取整,速度为负值Math.floor向下取整。

为什么正时Math.ceil向上取整,速度为负值Math.floor向下取整,当时学习的时候我也想不通,于是把Math.ceil(speed)和Math.floor(speed)拿来进行单独的测试,发现其中的原因。

Math.ceil(speed)来测试,改动代码(部分)如下:

timer = setInterval(function(){

				//非匀速运动的速度计算
				var speed = (target - divEle.offsetLeft)/10;

				//速度为正时Math.ceil向上取整,速度为负值Math.floor向下取整
				//这里必须分情况取整,不然物体运动停止时达不到目标值target
				speed = Math.ceil(speed);
				
				if(divEle.offsetLeft == target){ //面板全部移出/移入时,清空定时器,停止运动
					clearInterval(timer);
				}else{
					divEle.style.left = divEle.offsetLeft + speed +"px";
				}
				console.log(divEle.offsetLeft);
			},50); //每个50ms物体匀速运动 speed + "px"

测试结果如下图-1,图-2


图-1



图-2


由图-1可以看出鼠标划入划出,动画停止时,滑动面板并没有完整显示或隐藏,特别是鼠标滑出时,面板停止运动,但是却漏了一点出来,这是bug呀。为什么会出现这样的bug?原因是,面板停止运动时的left值只达到 -4.5px 、-196.4px,而不是0、-200px。我们来分析一下console.log(divEle.offsetLeft)输出的最后的值,即动画停止运动时divEle.offsetLeft的值,以鼠标划入做分析——鼠标划入时,要求面板以动画完整显示整个面板,即面板的 left 的最终值为 0 ,现在面板停止,divEle.offsetLeft为 -5 ,由代码中speed 的计算公式  var speed = (target - divEle.offsetLeft)/10; 可知 ,此时speed 的值为 0.5 ,然后用speed =Math.ceil(speed) 取整 得speed 的值为 0,计算出divEle.style.left = divEle.offsetLeft + speed +"px"; 所以left 的值一直是 -4.5,而定时器一直在运行,所以面板停止运动,实际是left的值每次计算出来都是同一个值,而不是定时器停止运行了:

timer = setInterval(function(){


//非匀速运动的速度计算
var speed = (target - divEle.offsetLeft)/10;

speed = Math.ceil(speed);

if(divEle.offsetLeft == target){ //面板全部移出/移入时,清空定时器,停止运动
clearInterval(timer);
}else{
divEle.style.left = divEle.offsetLeft + speed +"px";
}
console.log(divEle.offsetLeft);
},50); //每个


要解决上面的bug,必须在speed值为负时,采用Math.floor(speed)向上取整,而不是用Math.floor(speed)向下取整造成未达到终点前速度为0了;同理,只使用Math.foor(speed)也会出现此bug,所以需使用 speed = speed > 0?Math.ceil(speed):Math.floor(speed); 做判断取整。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值