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 相关文章推荐
彪哥1.1(智能表格)提供下载
Sep 07 Javascript
prototype 1.5 &amp; scriptaculous 1.6.1 学习笔记
Sep 07 Javascript
JS 文件大小判断的实现代码
Apr 07 Javascript
ASP.NET jQuery 实例14 在ASP.NET form中校验时间范围
Feb 03 Javascript
jquery中.add()的使用分析
Apr 26 Javascript
使用Node.js处理前端代码文件的编码问题
Feb 16 Javascript
jQuery使用ajax跨域获取数据的简单实例
May 18 Javascript
JS基于构造函数实现的菜单滑动显隐效果【测试可用】
Jun 21 Javascript
vue-cli创建的项目,配置多页面的实现方法
Mar 15 Javascript
JavaScript ES2019中的8个新特性详解
Feb 20 Javascript
微信小程序基于Taro的分享图片功能实践详解
Jul 12 Javascript
javascript实现摄像头拍照预览
Sep 30 Javascript
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
便携利器 — TECSUN PL-365简评
2021/03/02 无线电
PHP反转字符串函数strrev()函数的用法
2012/02/04 PHP
基于session_unset与session_destroy的区别详解
2013/06/03 PHP
PHP同时连接多个mysql数据库示例代码
2014/03/17 PHP
php获取字符串中各个字符出现次数的方法
2015/02/23 PHP
利用ajax和PHP实现简单的流程管理
2017/03/23 PHP
php解决安全问题的方法实例
2019/09/19 PHP
Document 对象的常用方法
2009/07/31 Javascript
通过JQuery实现win8一样酷炫的动态磁贴效果(示例代码)
2013/07/13 Javascript
javascript回车完美实现tab切换功能
2014/03/13 Javascript
For循环中分号隔开的3部分的执行顺序探讨
2014/05/27 Javascript
简单谈谈jQuery(function(){})与(function(){})(jQuery)
2014/12/19 Javascript
用svg制作富有动态的tooltip
2015/07/17 Javascript
jquery validation验证表单插件
2017/01/07 Javascript
对vue 键盘回车事件的实例讲解
2018/08/25 Javascript
JS 正则表达式验证密码、邮箱格式的实例代码
2018/10/28 Javascript
浅谈Angular7 项目开发总结
2018/12/19 Javascript
JS算法题之查找数字在数组中的索引位置
2019/05/15 Javascript
Net微信网页开发 使用微信JS-SDK获取当前地理位置过程详解
2019/08/26 Javascript
vue 组件间的通信之子组件向父组件传值的方式
2020/07/29 Javascript
[02:38]DOTA2亚洲邀请赛小组赛精彩集锦:Wings完美团击溃对手
2017/03/29 DOTA
python封装对象实现时间效果
2020/04/23 Python
Python三种遍历文件目录的方法实例代码
2018/01/19 Python
对python中的for循环和range内置函数详解
2018/04/17 Python
python 数字类型和字符串类型的相互转换实例
2018/07/17 Python
Flask框架Flask-Login用法分析
2018/07/23 Python
Ubuntu16.04安装python3.6.5步骤详解
2020/01/10 Python
解决python对齐错误的方法
2020/07/16 Python
python图片合成的示例
2020/11/09 Python
Python如何批量生成和调用变量
2020/11/21 Python
学前教育教师求职自荐信
2013/09/22 职场文书
民主生活会剖析材料
2014/09/30 职场文书
物业工程部主管岗位职责
2015/04/16 职场文书
欠条格式范本
2015/07/03 职场文书
MYSQL主从数据库同步备份配置的方法
2021/05/26 MySQL
python turtle绘制多边形和跳跃和改变速度特效
2022/03/16 Python