Javascript动画效果(3)


Posted in Javascript onOctober 11, 2016

前面我们已经介绍了速度动画、透明度动画、多物体运动和任意值变化,并且我们在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 相关文章推荐
让网页根据不同IE版本显示不同的内容
Feb 08 Javascript
Google的跟踪代码 动态加载js代码方法应用
Nov 12 Javascript
form表单中去掉默认的enter键提交并绑定js方法实现代码
Apr 01 Javascript
把jQuery的类、插件封装成seajs的模块的方法
Mar 12 Javascript
Javascript基础教程之函数对象和属性
Jan 18 Javascript
JavaScript知识点总结之如何提高性能
Jan 15 Javascript
基于node.js的fs核心模块读写文件操作(实例讲解)
Sep 10 Javascript
weebox弹出窗口不居中显示的解决方法
Nov 27 Javascript
详解ES6语法之可迭代协议和迭代器协议
Jan 13 Javascript
vue-router配合ElementUI实现导航的实例
Feb 11 Javascript
layer 关闭指定弹出层的例子
Sep 25 Javascript
jQuery实现日历效果
Sep 11 jQuery
JavaScript实现自动切换图片代码
Oct 11 #Javascript
Javascript动画效果(2)
Oct 11 #Javascript
Javascript动画效果(1)
Oct 11 #Javascript
原生Javascript和jQuery做轮播图简单例子
Oct 11 #Javascript
jQuery progressbar通过Ajax请求实现后台进度实时功能
Oct 11 #Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
Oct 11 #Javascript
Node.js的文件权限及读写flag详解
Oct 11 #Javascript
You might like
星际争霸 Starcraft 秘技补丁
2020/03/14 星际争霸
从C/C++迁移到PHP——判断字符类型的函数
2006/10/09 PHP
php笔记之:AOP的应用
2013/04/24 PHP
JavaScript创建命名空间的5种写法
2014/06/24 PHP
php无限极分类递归排序实现方法
2014/11/11 PHP
Yii获取当前url和域名的方法
2015/06/08 PHP
php、java、android、ios通用的3des方法(推荐)
2016/09/09 PHP
PHP编程实现微信企业向用户付款的方法示例
2017/07/26 PHP
ThinkPHP框架实现的邮箱激活功能示例
2018/06/15 PHP
使用jQuery简化Ajax开发 Ajax开发入门
2009/10/14 Javascript
JavaScript实现弹出子窗口并传值给父窗口
2014/12/18 Javascript
你所不了解的javascript操作DOM的细节知识点(一)
2015/06/17 Javascript
详解Bootstrap的aria-label和aria-labelledby应用
2016/01/04 Javascript
jQuery实现控制文字内容溢出用省略号(…)表示的方法
2016/02/26 Javascript
Vue中this.$router.push参数获取方法
2018/02/27 Javascript
有趣的JavaScript隐式类型转换操作实例分析
2020/05/02 Javascript
[01:16]2014DOTA2 TI专访C9战队EE:中国五强中会占三席
2014/07/10 DOTA
python中string模块各属性以及函数的用法介绍
2016/05/30 Python
Python+Wordpress制作小说站
2017/04/14 Python
python3通过selenium爬虫获取到dj商品的实例代码
2019/04/25 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
2019/07/11 Python
Python字符串的修改方法实例
2019/12/19 Python
快速解决jupyter notebook启动需要密码的问题
2020/04/21 Python
英国文胸专家:AmpleBosom.com
2018/02/06 全球购物
JBL澳大利亚官方商店:扬声器、耳机和音响系统
2018/05/24 全球购物
Java面试题:说出如下代码的执行结果
2015/10/30 面试题
成人毕业生自我鉴定
2013/10/18 职场文书
大三学生入党思想汇报
2014/01/02 职场文书
班组长安全工作职责
2014/07/15 职场文书
2014高中生入党思想汇报范文
2014/09/13 职场文书
五年级学生评语大全
2014/12/26 职场文书
活动总结书怎么写
2015/05/11 职场文书
心灵捕手观后感
2015/06/02 职场文书
庆七一主持词
2015/06/29 职场文书
2019通用版劳动合同范本!
2019/07/11 职场文书
零基础学java之带返回值的方法的定义和调用
2022/04/10 Java/Android