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 相关文章推荐
Mootools 1.2教程 滚动条(Slider)
Sep 15 Javascript
innerhtml用法 innertext用法 以及innerHTML与innertext的区别
Oct 26 Javascript
让FireFox支持innerText的实现代码
Dec 01 Javascript
从零开始学习jQuery (八) 插播:jQuery实施方案
Feb 23 Javascript
鼠标滑上去后图片放大浮出效果的js代码
May 28 Javascript
jQuery Mobile 导航栏代码
Nov 01 Javascript
JS计算网页停留时间代码
Apr 28 Javascript
javascript操作select元素实例分析
Mar 27 Javascript
JavaScript链式调用实例浅析
Dec 19 Javascript
webpack4手动搭建Vue开发环境实现todoList项目的方法
May 16 Javascript
vue使用canvas实现移动端手写签名
Sep 22 Javascript
JavaScript 中判断变量是否为数字的示例代码
Oct 22 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
桌面中心(四)数据显示
2006/10/09 PHP
PHP生成图片验证码、点击切换实例
2014/06/25 PHP
php基于base64解码图片与加密图片还原实例
2014/11/03 PHP
浅谈json_encode用法
2015/03/05 PHP
php获取访问者IP地址汇总
2015/04/24 PHP
php实现在服务器端调整图片大小的方法
2015/06/16 PHP
php实现mysql数据库分表分段备份
2015/06/18 PHP
再Docker中架设完整的WordPress站点全攻略
2015/07/29 PHP
一个实用的php验证码类
2017/07/06 PHP
详解php中serialize()和unserialize()函数
2017/07/08 PHP
jquery动态调整div大小使其宽度始终为浏览器宽度
2014/06/06 Javascript
js验证上传图片的方法
2015/05/12 Javascript
AngularJS中如何使用$parse或$eval在运行时对Scope变量赋值
2016/01/25 Javascript
关于cookie的初识和运用(js和jq)
2016/04/07 Javascript
利用Angularjs和bootstrap实现购物车功能
2016/08/31 Javascript
原生JS中slice()方法和splice()区别
2017/03/06 Javascript
深入理解基于vue-cli的vuex配置
2017/07/24 Javascript
vue 数组和对象不能直接赋值情况和解决方法(推荐)
2017/10/25 Javascript
解决Vue2.0 watch对象属性变化监听不到的问题
2018/09/11 Javascript
antd form表单数据回显操作
2020/11/02 Javascript
element-plus一个vue3.xUI框架(element-ui的3.x 版初体验)
2020/12/02 Vue.js
[06:36]吞吞映像top1
2014/06/20 DOTA
[01:45]典藏宝瓶2+祈求者身心——这就是DOTA2TI9总奖金突破3000万美元的秘密
2019/07/21 DOTA
详解Python网络爬虫功能的基本写法
2016/01/28 Python
Django重置migrations文件的方法步骤
2019/05/01 Python
搭建python django虚拟环境完整步骤详解
2019/07/08 Python
Django Channels 实现点对点实时聊天和消息推送功能
2019/07/17 Python
django自带调试服务器的使用详解
2019/08/29 Python
Python实现基于socket的udp传输与接收功能详解
2019/11/15 Python
django 利用Q对象与F对象进行查询的实现
2020/05/15 Python
便利店的创业计划书
2014/01/15 职场文书
电力公司个人求职信范文
2014/02/04 职场文书
幼教求职信
2014/03/12 职场文书
爱国主义教育活动总结
2014/05/07 职场文书
财务助理岗位职责范本
2014/10/09 职场文书
初中同学会致辞
2015/08/01 职场文书