利用原生JS与jQuery实现数字线性变化的动画


Posted in Javascript onFebruary 24, 2017

前言

大家应该都有所体会,在一些数据展示的专题页里,有时候希望数字能动态从某一个数变化到另一个数,以此来吸引用户眼球,突出数据。于是有了下文。

在这里,我用了两种方式:一种是原生的JavaScript,另一种是jQuery插件。

数字线性变化的原理很简单,就是让数字增量变化,并循环动画。

原生JS版

首先获取DOM元素。为了兼容到IE6,兼容性方法如下:

var domUtil = {
 // 获取DOM元素
 get: function(query) {
  var _this = this;
  if(document.querySelector) {
   return document.querySelector(query);
  } else {
   var elements = document;
   var queryStrArray = query.split(/ +/);
   for(var i = 0; i < queryStrArray.length; i++) {
    var domName = queryStrArray[i];
    elements = _this.getElementsOfParentNode(domName, elements);
   }
   if(elements.length == 1) {
    return elements[0];
   } else {
    return elements;
   }
  }
 },
 // 获取DOM元素
 getElementsOfParentNode: function(domName, parentNode) {
  var _this = this;
  parentNode = parentNode || document;
  domName = domName.trim();
  var regExps = {
   id: /^#/,
   class: /^/
  };
  if(regExps.id.test(domName)) {
   domName = domName.replace(/^\#/g, "");
   return parentNode.getElementById(domName);
  } else if(regExps.class.test(domName)) {
   domName = domName.replace(/^./g, "");
   return _this.getElementsByClassName(domName, parentNode);
  } else {
   return parentNode.getElementsByTagName(domName);
  }
 },
 // 获取class元素的兼容方法
 getElementsByClassName: function(className, parentNode) {
  if(parentNode.getElementsByClassName){
   return parentNode.getElementsByClassName(className);
  } else {
   className = className.replace(/^ +| +$/g,"");
   var classArray = className.split(/ +/);
   var eles = parentNode.getElementsByTagName("*");
   for(var i = 0;i < classArray.length; i++){
    var classEles = [];
    var reg = new RegExp("(^| )" + classArray[i] + "( |$)");
    for(var j = 0;j < eles.length; j++){
     var ele = eles[j];
     if(reg.test(ele.className)){
      classEles.push(ele);
     }
    }
    eles = classEles;
   }
   return eles;
  }
 }
};
/*
 * 数字动画(目前仅支持数字动画的线性变化)
 * options参数:
 *  element {String} DOM元素query字符串
 *  from {Number} 起始数字
 *  to {Number} 终点数字
 *  duration {Number} 动画时间
 *  callback {Function} 数字变化时的回调函数
 */
var animatingNumber = function(options) {
 this.element = domUtil.get(options.element);
 this.startNum = options.from;
 this.endNum = options.to;
 this.duration = options.duration || 2000;
 this.callback = options.callback;

 this.timer = null;
};

animatingNumber.prototype = {
 start: function() {
  var _this = this;
  _this.animate();
 },
 stop: function() {
  if(this.timer) {
   clearTimeout(this.timer);
   this.timer = null;
  }
 },
 animate: function() {
  var _this = this;
  var curNum = _this.startNum;
  var animateTime = 0;
  var range = _this.endNum - _this.startNum;
  var timerStep = Math.abs( Math.floor(_this.duration / range) );
  timerStep = timerStep > 20 ? timerStep : 20;
  var numStep = (range / _this.duration) * timerStep;

  _this.stop();

  (function animate() {
   _this.timer = setTimeout(function() {
    curNum = Math.ceil( curNum + numStep );
    if( (_this.endNum > _this.startNum && curNum >= _this.endNum) || (_this.endNum < _this.startNum && curNum <= _this.endNum) ) {
     curNum = _this.endNum;
    }
    _this.element.innerText = curNum;
    animateTime++;
    if(typeof this.callback == 'function') {
     this.callback(curNum);
    }
    animate();
    if(curNum >= _this.endNum) {
     _this.stop();
    }
   }, timerStep);
  })();
 }
};

animatingNumber.create = function(options) {
 return new animatingNumber(options);
};

使用:

<p>Number: <span class='dynamicNum'>500</span></p>

<script>
 animatingNumber.create({
  element: '.dynamicNum',
  from: 1,
  to: 500,
  duration: 2000
 }).start();
</script>

jQuery插件版

原理同上,只是DOM元素获取使用jQuery方法,并把数字动画方法封装成jQuery插件。

如下:

/*
 * 数字动画(目前仅支持数字动画的线性变化)
 * options参数:
 *  from {Number} 起始数字
 *  to {Number} 终点数字
 *  duration {Number} 动画时间
 *  callback {Function} 数字变化时的回调函数
 */
(function( $ ) {
 $.fn.animatingNumber = function(options) {
  var settings = {
   element: this,
   startNum: options.from,
   endNum: options.to,
   duration: options.duration || 2000,
   callback: options.callback
  };
  var timer = null;

  var methods = {
   start: function() {
    var _this = this;
    _this.animate();
   },
   stop: function() {
    if(timer) {
     clearTimeout(timer);
     timer = null;
    }
   },
   animate: function() {
    var _this = this;
    var curNum = settings.startNum;
    var animateTime = 0;
    var range = settings.endNum - settings.startNum;
    var timerStep = Math.abs( Math.floor(settings.duration / range) );
    timerStep = timerStep > 20 ? timerStep : 20;
    var numStep = (range / settings.duration) * timerStep;

    _this.stop();

    (function animate() {
     timer = setTimeout(function() {
      curNum = Math.ceil( curNum + numStep );
      if( (settings.endNum > settings.startNum && curNum >= settings.endNum) || (settings.endNum < settings.startNum && curNum <= settings.endNum) ) {
       curNum = settings.endNum;
      }
      settings.element.text(curNum);
      animateTime++;
      if(typeof settings.callback == 'function') {
       settings.callback(curNum);
      }
      animate();
      if(curNum >= settings.endNum) {
       _this.stop();
      }
     }, timerStep);
    })();
   }
  };
  return this.each(function() {
   return methods.start();
  });

 };
})( jQuery );

使用:

<p>Number: <span class='dynamicNum'></span></p>

<script>
$('.dynamicNum').animatingNumber({
 from: 1,
 to: 1000,
 duration: 2000
});
</script>

最后

好了,以上就是这篇文章的全部内容了,后期会考虑加上缓动函数的选择项。希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
关于javascript中的parseInt使用技巧
Sep 03 Javascript
javascript学习笔记(十九) 节点的操作实现代码
Jun 20 Javascript
Javascript继承(上)——对象构建介绍
Nov 08 Javascript
使用jQuery实现更改默认alert框体
Apr 13 Javascript
总结JavaScript设计模式编程中的享元模式使用
May 21 Javascript
javascript insertAfter()定义与用法示例
Jul 25 Javascript
JavaScript第一篇之实现按钮全选、功能
Aug 21 Javascript
AngularJs ng-route路由详解及实例代码
Sep 14 Javascript
jQuery实现Table表格隔行变色及高亮显示当前选择行效果示例
Feb 14 Javascript
浅谈js中function的参数默认值
Feb 20 Javascript
Vue自定义指令封装节流函数的方法示例
Jul 09 Javascript
JS面向对象实现飞机大战
Aug 26 Javascript
JavaScript和jQuery制作光棒效果
Feb 24 #Javascript
微信小程序 动态的设置图片的高度和宽度详解及实例代码
Feb 24 #Javascript
微信小程序实现实时圆形进度条的方法示例
Feb 24 #Javascript
JavaScript中三种常见的排序方法
Feb 24 #Javascript
Angular2 Service实现简单音乐播放器服务
Feb 24 #Javascript
Bootstrap3多级下拉菜单
Feb 24 #Javascript
使用原生的javascript来实现轮播图
Feb 24 #Javascript
You might like
php实现的数字验证码及数字运算验证码
2015/07/30 PHP
纯php生成随机密码
2015/10/30 PHP
PHP+ajax分页实例简析
2015/12/07 PHP
YiiFramework入门知识点总结(图文教程)
2015/12/28 PHP
利用PHP如何写APP接口详解
2016/08/23 PHP
php读取qqwry.dat ip地址定位文件的类实例代码
2016/11/15 PHP
PHP简单装饰器模式实现与用法示例
2017/06/22 PHP
php如何修改SESSION的生存存储时间的实例代码
2017/07/05 PHP
JavaScript之引用类型介绍
2012/08/10 Javascript
JavaScript中使用document.write向页面输出内容实例
2014/10/16 Javascript
推荐4个原生javascript常用的函数
2015/01/12 Javascript
iframe里使用JavaScript控制主页转向的方法
2015/04/03 Javascript
深入分析jsonp协议原理
2015/09/26 Javascript
jQuery Tree Multiselect使用详解
2017/05/02 jQuery
jQuery实现参数自定义的文字跑马灯效果
2018/08/15 jQuery
解决vue无法设置滚动位置的问题
2018/10/07 Javascript
vue移动端html5页面根据屏幕适配的四种解决方法
2018/10/19 Javascript
vue resource发送请求的几种方式
2019/09/30 Javascript
js判断复选框是否选中的方法示例【基于jQuery】
2019/10/10 jQuery
vue 实现特定条件下绑定事件
2019/11/09 Javascript
详解JS深拷贝与浅拷贝
2020/08/04 Javascript
[15:58]DOTA2国际邀请赛采访专栏:Tongfu.Sansheng&KingJ,DK.rOtk
2013/08/08 DOTA
[01:22:42]2014 DOTA2华西杯精英邀请赛 5 24 DK VS LGD
2014/05/26 DOTA
K-近邻算法的python实现代码分享
2017/12/09 Python
python 实现对文件夹内的文件排序编号
2018/04/12 Python
python中多个装饰器的执行顺序详解
2018/10/08 Python
Django中使用Whoosh进行全文检索的方法
2019/03/31 Python
介绍一款python类型检查工具pyright(推荐)
2019/07/03 Python
在自动化中用python实现键盘操作的方法详解
2019/07/19 Python
Linux上比较文件的命令都有哪些
2012/02/24 面试题
2014年招商工作总结
2014/11/22 职场文书
2015年高三教学工作总结
2015/07/21 职场文书
公司员工宿舍管理制度
2015/08/03 职场文书
Python Flask实现进度条
2022/05/11 Python
关于Redis的主从复制及哨兵问题
2022/06/16 Redis
python中validators库的使用方法详解
2022/09/23 Python