利用原生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 相关文章推荐
js变量作用域及可访问性的探讨
Nov 23 Javascript
jQuery bind事件使用详解
May 05 Javascript
jqueyr判断checkbox组的选中(示例代码)
Nov 08 Javascript
javascript判断css3动画结束 css3动画结束的回调函数
Mar 10 Javascript
Javascript操作表单实例讲解(下)
Jun 20 Javascript
jQuery新窗口打开外链接
Jul 21 Javascript
Jil,高效的json序列化和反序列化库
Feb 15 Javascript
js用类封装pop弹窗组件
Oct 08 Javascript
js+html获取系统当前时间
Nov 10 Javascript
Egg.js 中 AJax 上传文件获取参数的方法
Oct 10 Javascript
利用Node.js如何实现文件循环覆写
Apr 05 Javascript
基于canvasJS在PHP中制作动态图表
May 30 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
yiic命令时提示“php.exe”不是内部或外部命令的解决方法
2014/12/18 PHP
php实现分页显示
2015/11/03 PHP
php遍历解析xml字符串的方法
2016/05/05 PHP
PHP图片裁剪与缩放示例(无损裁剪图片)
2017/02/08 PHP
php获取linux命令结果的实例
2017/03/13 PHP
jquery的颜色选择插件实例代码
2008/10/02 Javascript
EasyUI 中 MenuButton 的使用方法
2012/07/14 Javascript
AngularJS实现全选反选功能
2015/12/08 Javascript
js操作XML文件的实现方法兼容IE与FireFox
2016/06/25 Javascript
easyui中combotree循环获取父节点至根节点并输出路径实现方法
2016/11/10 Javascript
jQuery实现的弹幕效果完整实例
2017/09/06 jQuery
react 实现页面代码分割、按需加载的方法
2018/04/03 Javascript
简单明了区分escape、encodeURI和encodeURIComponent
2018/05/26 Javascript
JavaScript学习笔记之数组基本操作示例
2019/01/09 Javascript
详解JS实现系统登录页的登录和验证
2019/04/29 Javascript
原生js+canvas实现下雪效果
2020/08/02 Javascript
Vue实现一种简单的无限循环滚动动画的示例
2021/01/10 Vue.js
Cpy和Python的效率对比
2015/03/20 Python
Python检测字符串中是否包含某字符集合中的字符
2015/05/21 Python
深入讲解Python中的迭代器和生成器
2015/10/26 Python
Python如何为图片添加水印
2016/11/25 Python
opencv python 图像轮廓/检测轮廓/绘制轮廓的方法
2019/07/03 Python
python多任务之协程的使用详解
2019/08/26 Python
Python txt文件常用读写操作代码实例
2020/08/03 Python
经管应届生求职信
2013/11/17 职场文书
大学四年职业生涯规划书范文
2014/01/02 职场文书
八年级音乐教学反思
2014/01/09 职场文书
销售主管岗位职责
2014/02/08 职场文书
六一文艺汇演开幕词
2015/01/29 职场文书
民间借贷借条如何写
2015/05/26 职场文书
怎样写好工作计划
2019/04/10 职场文书
python基础学习之生成器与文件系统知识总结
2021/05/25 Python
教你如何使用Python开发一个钉钉群应答机器人
2021/06/21 Python
深入浅析python3 依赖倒置原则(示例代码)
2021/07/09 Python
python编程项目中线上问题排查与解决
2021/11/01 Python
JavaWeb Servlet开发注册页面实例
2022/04/11 Java/Android