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{ width: 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, {
width: 400,
height: 200,
opacity: 100
});
};
Li.onmouseout = function() {
startMove(Li, {
width: 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{ width: 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:202,height:200,opacity:100});
};
Li.onmouseout = function(){
startMove(Li,{width: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动画效果(三)的更多相关文章

  1. Javascript动画效果(一)

    Javascript动画效果(一) 前面我们介绍了Javascript的回到顶部效果,今天呢,我们对Javascript动画做进一步的研究.在这篇博文中我们只介绍简单的匀速运动.简单的缓冲运动和简单的 ...

  2. Javascript动画效果(二)

    Javascript动画效果(二) 在前面的博客中讲了简单的Javascript动画效果,这篇文章主要介绍我在改变之前代码时发现的一些问题及解决方法. 在前面的多物体宽度变化的例子中,我们给其增加代码 ...

  3. Javascript动画效果(四)

    Javascript动画效果(四) 前面我们自己写了一个小小的关于js动画的插件,下面我们来使用之前的框架来完成我们想要的动画效果.我们经常在淘宝网中看到,鼠标经过某一图片时,该图片有从上滚出而又从下 ...

  4. javascript动画效果之缓冲动画(修改版)

    在编写多块同时触发运动的时候,发现一个BUG, timer = setInterval(show, 30);本来show是一个自定义函数,当设为timer = setInterval(show(one ...

  5. javascript动画效果之透明度(修改版)

    在编写多块同时触发运动的时候,发现一个BUG, timer = setInterval(show, 30);本来show是一个自定义函数,当设为timer = setInterval(show(one ...

  6. javascript动画效果之匀速运动(修订版)

    在编写多块同时触发运动的时候,发现一个BUG, timer = setInterval(show, 30);本来show是一个自定义函数,当设为timer = setInterval(show(one ...

  7. 【BOOM】一款有趣的Javascript动画效果

    实践出真知,有的时候看到一些有趣的现象就想着用自己所学的知识复现一下.    boomJS 缘起 前几天在 github 上看到同事的一个这样的小项目,在 IOS 上实现了这样一个小动画效果,看上去蛮 ...

  8. javascript动画效果

    之前工作项目中,运用了缓动动画的效果,在网上看到其他大牛写的相关公式,结合工作需要,进行了整理,拿出来跟大家分享下,js代码中,只运用了一个小功能进行了测试 <!DOCTYPE html> ...

  9. javascript动画效果之任意效果任意值

    通过学习,我发现当同一个ul下的li标签如果想要不同的效果,那怎么办? 比如第一个li是width变化,第二个li为透明度(opacity)变化,而opacity的值和width的值类型不同,不能通用 ...

随机推荐

  1. Win10 UWP应用发布流程

    简介 Win10 UWP应用作为和Win8.1 UAP应用不同的一种新应用形式,其上传至Windows应用商店的流程也有了一些改变. 这篇博文记录了我们发布一款Win10 UWP应用的基本流程,希望为 ...

  2. MSBuild 中的 PropertyGroup、ItemGroup 和 ItemMetadata

    在软件项目不断的进展中,MSBuild 脚本可能几个月都不会被修改,因为通常编译和发布的目录是不经常变化的. 但,一旦某天你需要修改了,看到那一堆 $(Something). @(Something) ...

  3. Sublime Text 2—解决中文乱码

    Sublime Text 2是一个非常棒的代码及文本编辑器,绿色小巧.速度飞快,跨平台支持Win/Mac/Linux,支持32与64位,支持各种流行编程语言的语法高亮.代码补全等,有着许多其他编辑器没 ...

  4. [ACM_动态规划] Alignment (将军排队)

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28415#problem/F 题目大意:有n个士兵排成一列,将军想从中抽出最少人数使队伍中 ...

  5. jQuery的attr与prop

    jQuery1.6中新添加了一个prop方法,看起来和用起来都和attr方法一样,这两个方法有什么区别呢?这要从HTMl 的attribute与property区别说起,attr与prop正是这两个东 ...

  6. 远程调试 Azure Web App

    当我们将 Web App 部署在 Azure 上时,如果能够实现远程调试,将会极大的提高我们修复 bug 的效率.Visual Studio 一贯以功能强大.易用著称,当然可以实现基于 Azure 应 ...

  7. JS数组的concat、push等方法,操作的是地址指针,而非内存操作

    var a = [{x:1}, {y:1}, {z:3}]; var b = a.concat(['gg', 'ff']); var c = []; c.push(a[1]); console.log ...

  8. C#学习系列-out与ref的区别

    参考:http://www.microsoftvirtualacademy.com/Content/ViewContent.aspx?et=9851&m=9839&ct=31056 如 ...

  9. flow.ci + Github + Slack 一步步搭建 Python 自动化持续集成

    理想的程序员必须懒惰,永远追随自动化法则.Automating shapes smarter future. 在一个 Python 项目的开发过程中可能会做的事情:编译.手动或自动化测试.部署环境配置 ...

  10. 35.按要求编写Java程序: (1)编写一个接口:InterfaceA,只含有一个方法int method(int n); (2)编写一个类:ClassA来实现接口InterfaceA,实现int method(int n)接口方 法时,要求计算1到n的和; (3)编写另一个类:ClassB来实现接口InterfaceA,实现int method(int n)接口 方法时,要求计算n的阶乘(n

      35.按要求编写Java程序: (1)编写一个接口:InterfaceA,只含有一个方法int method(int n): (2)编写一个类:ClassA来实现接口InterfaceA,实现in ...