利用原生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 面向对象全新理练之继承与多态
Dec 03 Javascript
原生JS实现加入收藏夹的代码
Oct 24 Javascript
javascript学习笔记(一)基础知识
Sep 30 Javascript
JavaScript数据类型判定的总结笔记
Jul 31 Javascript
bootstrapfileinput实现文件自动上传
Nov 08 Javascript
Bootstrap CSS布局之按钮
Dec 17 Javascript
Bootstrap table右键功能实现方法
Feb 20 Javascript
javascript中的相等操作符(==与===区别)
Dec 21 Javascript
Node.js+Vue脚手架环境搭建的方法步骤
Mar 08 Javascript
如何优雅地取消 JavaScript 异步任务
Mar 22 Javascript
JS实现电脑虚拟键盘打字测试
Jun 24 Javascript
JavaScript 空间坐标的使用
Aug 19 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 获取目录下的图片并随机显示的代码
2009/12/28 PHP
PHP set_time_limit(0)长连接的实现分析
2010/03/02 PHP
php提示undefined index的几种解决方法
2012/05/21 PHP
PHP删除数组中特定元素的两种方法
2013/07/02 PHP
php增删改查示例自己写的demo
2013/09/04 PHP
PHP中把错误日志保存在系统日志中(Windows系统)
2015/06/23 PHP
PHP使用Curl实现模拟登录及抓取数据功能示例
2018/04/27 PHP
Yii使用DbTarget实现日志功能的示例代码
2020/07/21 PHP
使用原生javascript创建通用表单验证——更锋利的使用dom对象
2011/09/13 Javascript
jquery iframe操作详细解析
2013/11/20 Javascript
CSS图片响应式 垂直水平居中
2015/08/14 Javascript
webpack+vue.js实现组件化详解
2016/10/12 Javascript
有趣的bootstrap走动进度条
2016/12/01 Javascript
web打印小结
2017/01/11 Javascript
Vue 滚动行为的具体使用方法
2017/09/13 Javascript
jupyter安装小结
2016/03/13 Python
Windows下Python使用Pandas模块操作Excel文件的教程
2016/05/31 Python
Python如何实现文本转语音
2016/08/08 Python
python Socket之客户端和服务端握手详解
2017/09/18 Python
关于Python的一些学习总结
2018/05/25 Python
Python 使用PIL中的resize进行缩放的实例讲解
2018/08/03 Python
Python JSON编解码方式原理详解
2020/01/20 Python
基于Python中random.sample()的替代方案
2020/05/23 Python
图解CSS3制作圆环形进度条的实例教程
2016/05/26 HTML / CSS
size?瑞典:英国伦敦的球鞋精品店
2018/03/01 全球购物
美国手工艺品市场的领导者:Annie’s
2019/04/04 全球购物
Oracle快照(snapshot)
2015/03/13 面试题
通信工程专业女生个人求职信
2013/09/21 职场文书
个人找工作求职简历的自我评价
2013/10/20 职场文书
2014年党员公开承诺书范文
2014/03/28 职场文书
本科毕业生自荐信
2014/06/02 职场文书
学校与家长安全责任书
2014/07/23 职场文书
学习张丽丽心得体会
2014/09/03 职场文书
2014年个人工作总结报告
2014/11/27 职场文书
事业单位个人总结
2015/02/12 职场文书
针对吵架老公保证书
2015/05/08 职场文书