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. java反射机制初探

    最近和一位师兄交流了一下Java,真可谓是大有收获,让我好好的学习了一下javad的反射机制,同终于明白了spring等框架的一个基本实现的思想,那么今天就和大家分享一下java的反射机制. 反射,r ...

  2. 负载均衡的mariadb集群搭建

    集群介绍: Galera是一个MySQL(也支持MariaDB,Percona)的同步多主集群软件,目前只支持InnoDB引擎. 主要功能: 同步复制 真正的multi-master,即所有节点可以同 ...

  3. file /usr/share/mysql/... conflicts with file from package mysql-libs-5.1.73-3.el6_5.x86_ 64 MySQL安装

    在CentOS 6.5安装MySQL 5.6.17,安装到最后一个rpm文件MySQL-server时 安装命令是:rpm -ivh MySQL-server-5.6.17-1.el6.x86_64. ...

  4. Blend 2015 教程 (三) 模板

    前一篇讲述了一些基本样式的修改方法,并搭建了Style层的基本框架,本篇将进一步修改ListBox的样式. 1. 首先选中ListBox控件,在美工板导航栏中点击ListBox,选择 编辑其他模板-编 ...

  5. 使用https的HSTS需要注意的一个问题

    HSTS(HTTP Strict Transport Security) 简单来说就是由浏览器进行http向https的重定向.如果不使用HSTS,当用户在浏览器中输入网址时没有加https,浏览器会 ...

  6. JQuery源码解析(一)

    写在前面:本<JQuery源码解析>系列是基于一些前辈们的文章进行进一步的分析.细化.修改而写出来的,在这边感谢那些慷慨提供科普文档的技术大拿们. 要查阅JQ的源文件请下载开发版的JQ.j ...

  7. [stm32] 一个简单的stm32vet6驱动2.4寸240X320的8位并口tft屏DEMO

    书接上文: 最近在研究用低速.低RAM的单片机来驱动小LCD或TFT彩屏实现动画效果 首先我用一个16MHz晶振的m0内核的8位单片机nRF51822尝试驱动一个1.77寸的4线SPI屏(128X16 ...

  8. 翻译-DevOps究竟是什么?

    原文地址:http://www.drdobbs.com/architecture-and-design/what-exactly-is-devops/240009147 作者:Neil Garnich ...

  9. 泛型实现中没有正确lock引用类型的一个隐藏bug分析

    最近看到这篇文章dotNetDR_的回复,让我想起一个真实发生的案例,下面就简单说说这个关于lock引用类型的一个不容易发现的隐藏缺陷. 某类库中的代码,封装了很简单的一个通用类,用于线程安全地执行某 ...

  10. JVM内存回收机制简述

    JVM内存回收机制涉及的知识点太多了,了解越多越迷糊,汗一个,这里仅简单做个笔记,主要参考<深入理解Java虚拟机:JVM高级特性与最佳实践(第二版)> 目前java的jdk默认虚拟机为H ...