Javascript动画效果(三)

摘要:
Javascript动画效果(III)我们引入了速度动画、透明度动画、多对象运动和任意值更改,并在Javascript动画效应(II)中封装了一个简单的插件原型。接下来,我们将进一步扩展之前的动画效果,并尝试使我们的框架更实用。Math.ceil:Math.floor;如果{clearInterval;如果{fn();}}else{如果{obj.style.filter='alpha';obj.style.opacity=/100;}else{obj.style[attr]=icur+speed+'px';},30)}functiongetStyle{如果{returnobj.currentStyle[attr];}否则{returngetComputeStyle[attr;}2。同时移动是指同时移动,你可能会发现它非常简单,可以通过在onmouseover事件之后直接添加两个不同的starMove()函数来解决(错误的想法!

Javascript动画效果(三)

前面我们已经介绍了速度动画、透明度动画、多物体运动和任意值变化,并且我们在Javascript动画效果(二)中介绍到我们封装了一个简单的插件雏形,接下来我们对前面的动画效果进行进一步扩充,尽量将我们的框架做到更实用。在这里我们还需要了解两个运动,一个是链式运动,一个是同时运动。它们间的区别分别是:链式运动是指运动一个接着一个(一个运动完成马上进行下一个运动);而同时运动是指所有的运动同时进行。在这里,我们该如何实现呢?

1、链式运动

  前面的效果中,我们已经能对任意值进行相应的变化,我们该如何在一个动画后添加一个动画呢?

  思路:我们能不能在参数中传入一个函数,当一个效果完成后马上执行后面的函数(效果),该函数可以是想要的动画效果

  实现:在function startMove(obj,attr,iTarget)中在传入一个参数fn,代表一个函数。这时我们还需要修改的有在定时器的后面增加一个判断if(fn){fn(); },当存在fn函数时执行fn函数,当不存在fn函数时清除定时器。这样我们的window.onload函数也应该发生相应变化,代码如下:

window.onload = function() {
	var Li = document.getElementById('li1');
	Li.onmouseover = function() {
		startMove(Li, 'width', 400, function() {
			startMove(Li, 'height', 200, function() {
				startMove(Li, 'opacity', 100);
			});
		});
	};
	Li.onmouseout = function() {
		startMove(Li, 'opacity', 30, function() {
			startMove(Li, 'height', 100, function() {
				startMove(Li, 'width', 200);
			});
		});
	};
};

所以我们得到链式运动的如下代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>链式运动</title>
		<style type="text/css">
			body,ul,li{ margin: 0px; padding: 0px; }
			ul,li{ list-style: none; }
			ul li{  200px; height: 100px; background: yellow; margin-bottom: 20px; border: 4px solid #000; filter:alpha(opacity:30); opacity:0.3; }
		</style>
		
	</head>
	<body>
		<ul>
			<li id="li1"></li>
		</ul>
		<script type="text/javascript">
			window.onload = function(){
				var Li = document.getElementById('li1');
				Li.onmouseover = function(){
					startMove(Li,'width',400,function(){
						startMove(Li,'height',200,function(){
							startMove(Li,'opacity',100);
						});
					});
				};
				Li.onmouseout = function(){
					startMove(Li,'opacity',30,function(){
						startMove(Li,'height',100,function(){
							startMove(Li,'width',200);
						});
					});
				};
			};
		
			function startMove(obj,attr,iTarget,fn){
				clearInterval(obj.timer);
				obj.timer = setInterval(function(){
					var icur = 0;
					if(attr == 'opacity'){
						icur = Math.round(parseFloat(getStyle(obj,attr))*100);
					}else{
						icur = parseInt(getStyle(obj,attr));
					}
					var speed = (iTarget - icur)/10;
					speed = speed>0?Math.ceil(speed):Math.floor(speed);
					if(iTarget == icur){
						clearInterval(obj.timer);
						if(fn){
							fn();
						}
					}
					else{
						if(attr == 'opacity'){
							obj.style.filter = 'alpha(opacity:'+(icur+speed)+')';
							obj.style.opacity = (icur+speed)/100;
						}
						else{
							obj.style[attr] = icur+speed+'px';
						}
					}
				},30)
			}		
			
			function getStyle(obj,attr){
				if(obj.currentStyle){
					return obj.currentStyle[attr];
				}
				else{
					return getComputedStyle(obj,false)[attr];
				}
			}
		</script>
	</body>
</html>

2、同时运动

说到同时运动,你可能会觉得很简单,直接在onmouseover事件后面同时添加两个不同的starMove()函数就可以解决了(错误思路!),实际上并不是这样的,当有多个效果时,我们看到的是最后添加的那个效果。也就是说我们想同时改变宽度和高度(高度在后),我们得到的效果为只改变高度,宽度并没有变化。这里我们应该继续传参数么?从链式运动来看,传参数的效果只能在后面添加函数得到连续的动画效果。

  思路:我们可不可以用JSON的方法来同时改变多个动画效果?

  实现:将function startMove(obj,attr,iTarget,fn)中的attr和iTarget合并为一个参数:json,我们用for/in的方法来遍历json中的数据,例如:

var json = {"a":12,"b":21};
for(var attr in json){
	alert(json);//结果分别是:a,b
	alert(json[attr]);//结果分别是:12,21
}

 按照此方法,我们依次改变前面的代码:在定时器函数的后面加上代码:for(var attr in json) {...},并且修改里面的iTarget为json[attr],再将window.onload函数修改为:

window.onload = function() {
	var Li = document.getElementById('li1');
	Li.onmouseover = function() {
		startMove(Li, {
			 400,
			height: 200,
			opacity: 100
		});
	};
	Li.onmouseout = function() {
		startMove(Li, {
			 200,
			height: 100,
			opacity: 30
		});
	};
};

 这时我们差不多就可以得到我们想要的效果了,但是这样离我们最终的效果还是查了那么一点点,比如说我们将onmouseover事件中的starMove中的width修改为202,再执行我们的代码,我们会发现最终的height不是200px,opacity也不是100,如图:

这样就很尴尬了,之前我们的效果不是还蛮好的么?我们再回到我们的JS代码中分析结构,觉得最有可能出错的就是starMove函数中,我们发现这段代码的意思有点难理解:

if(json[attr] == icur) {
    clearInterval(obj.timer);
    if(fn) {
        fn();
    }
}

我们并不知道是不是所有的运动都到达终点时停止所有运动还是当只有一个运动达到终点时立马停止所有运动。但是通过我们前面的操作,可以知道的实际结果为,只有一个运动到达终点值时,所有的运动都停止了(此时还有运动没执行完),我们该如何进行操作呢?

  思路:我们可以假定一个参数flag,并且赋值为true,在执行clearInterval(obj.timer);操作前我们先进行判断if(json[attr] != icur) { flag = false;},后面执行之前else里面的语句,再执行如下语句if(flag = true) {clearInterval(obj.timer); if(fn) {fn();}},这样我们就可以得到同时运动的完整代码如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>链式运动</title>
		<style type="text/css">
			body,ul,li{ margin: 0px; padding: 0px; }
			ul,li{ list-style: none; }
			ul li{  200px; height: 100px; background: yellow; margin-bottom: 20px; border: 4px solid #000; filter:alpha(opacity:30); opacity:0.3; }
		</style>
		
	</head>
	<body>
		<ul>
			<li id="li1"></li>
		</ul>

		<script type="text/javascript">
			window.onload = function(){
				var Li = document.getElementById('li1');
				Li.onmouseover = function(){
					startMove(Li,{202,height:200,opacity:100});
				};
				Li.onmouseout = function(){
					startMove(Li,{200,height:100,opacity:30});
				};
			};
			
			function getStyle(obj, attr) {
				if(obj.currentStyle) {
					return obj.currentStyle[attr];
				} else {
					return getComputedStyle(obj, false)[attr];
				}
			}
			
			function startMove(obj, json, fn) {
				//定义标杆
				var flag = true; //假设的
			
				clearInterval(obj.timer);
				obj.timer = setInterval(function() {
					for(var attr in json) {
						var icur = 0;
						if(attr == 'opacity') {
							icur = Math.round(parseFloat(getStyle(obj, attr)) * 100);
						} else {
							icur = parseInt(getStyle(obj, attr));
						}
						var speed = (json[attr] - icur) / 10;
						speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
						if(json[attr] != icur) {
							flag = false;
						}
						if(attr == 'opacity') {//判断是否为opacity
							obj.style.filter = 'alpha(opacity:' + (icur + speed) + ')';
							obj.style.opacity = (icur + speed) / 100;
						} else {
							obj.style[attr] = icur + speed + 'px';
						}
						if(flag){
							clearInterval(obj.timer);
							if(fn){
								fn();
							}
						}	
					}
				}, 30)
			}
		</script>
	</body>
</html>

 这样我们的同时运动的动画效果就实现了。在这里,你有没有觉得很神奇?

在这里我们已经将一个简单的运动插件封装完成了,我们将里面的代码做一些解释,并且将它保存为一个foodoir.animate.js文件,代码如下:

/*
 * 简单的运动框架
 * 作者:foodoir
 * 此框架仅作参考!!!
 * 
 * 使用方法见博文
 */

function getStyle(obj, attr) {
	if(obj.currentStyle) {
		return obj.currentStyle[attr];
	} else {
		return getComputedStyle(obj, false)[attr];
	}
}

function startMove(obj, json, fn) {

	clearInterval(obj.timer); //清除定时器,避免重复生成多个定时器
	obj.timer = setInterval(function() {
		var flag = true; //假设刚开始时所有运动都已完成
		for(var attr in json) { //遍历json

			var icur = null;
			//1.判断类型
			if(attr == 'opacity') {
				icur = Math.round(parseFloat(getStyle(obj, attr)) * 100);
			} else {
				icur = parseInt(getStyle(obj, attr));
			}
			//2.算速度
			var speed = (json[attr] - icur) / 5;
			speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
			//3.检测停止
			if(icur != json[attr]) {
				flag = false;
			}
			if(attr == 'opacity') {
				obj.style.filter = 'alpha(opacity:' + (icur + speed) + ')';
				obj.style.opacity = (icur + speed) / 100;
			} else {
				obj.style[attr] = icur + speed + 'px';
			}
		}
		if(flag) { //当所有运动都完成时,清除定时器
			clearInterval(obj.timer);
			if(fn) {
				fn();
			}
		}
	}, 30);
}

 后面,我们将介绍用自己的框架来实现多种动画效果,并且和jquery中的动画效果进行比较。

免责声明:文章转载自《Javascript动画效果(三)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇.NET的MVVM框架linux 修改时区不生效下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

js获取移动端设备信息(IMEM,IMIS,手机型号,系统版本,浏览器信息等)

方法一: HTML+  封装好的方法,额外配置,使用指定方法打包才可用 属性: imei: 设备的国际移动设备身份码 imsi: 设备的国际移动用户识别码 model: 设备的型号 vendor: 设备的生产厂商 uuid: 设备的唯一标识 参考地址: http://www.html5plus.org/doc/zh_cn/device.htm...

使用C/C++ 实现ShellCode编写与提取

简单来说,shell code 的核心就是把代码写成 “与地址无关” 的风格,让它不论是在什么环境下都可以被执行。 具体注意: 使用 API 时应该动态调用(GetProAddress) 不能使用全局变量,或者用 static 修饰的变量 在 shellcode 工程中要自定义入口函数 确保调用 API 之前都已经加载了与之对应的 DLL 所有的字符串都...

运动曲线提升CSS动画效果

原文链接 译文译者鞠大宝   先有UI动画,然后才会有好的UI动画。好的动画会让人惊叹“哇哦!”——因为页面看上去很流畅、很漂亮,最重要的是,自然,一点都不会让人觉得不和谐或者僵硬死板。如果你经常逛Dribbble或者 UpLabs这类网站的话,你就会明白我在说什么了。 一些极好的拓展阅读资源:  ·SVG和CSS的路径剪辑动画  ·若干实用的动画技术  ...

高斯键盘设置指南

高斯键盘设置指南 蓝牙模式 如何打开蓝牙模式 供电 : 蓝牙工作需要供电, 给高斯 GS87-D 供电有两种方式: 键盘背后的开关打到ON; 使用 USB Type-C 电源. 切换模式: 有线和无线模式切换键是 Fn+P 按下 Fn+P 右上角键盘灯闪烁 3 次, 有线模式和蓝牙模式互相切换. 但比较坑的是并没有指示灯表示当前处于有线模式还是蓝...

js 提示窗

/** * @Co.,Ltd. 千寻前端 * @authors 小石头(1348571886@qq.com) * @date 2014-12-22 * @version 4.0 */ var jAlert=(function(){ this.myalertin=function(text,color...

Rust 智能指针(一)

Rust 智能指针(一) 1.Box<T> Box<T>是指向堆中的指针。 fn main() { let box = Box::new(3); println!("{}", box); } 在出了指针的作用域之后,指针和它指向的对象都将被释放。 在本例中,box将在main函数之后被释放。 由于Box<T&...