利用原生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 函数分析(转)
Mar 21 Javascript
jquery dialog open后,服务器端控件失效的快速解决方法
Dec 19 Javascript
直接在JS里创建JSON数据然后遍历使用
Jul 25 Javascript
Jquery通过JSON字符串创建JSON对象
Aug 24 Javascript
jQuery级联操作绑定事件实例
Sep 02 Javascript
express的中间件cookieParser详解
Dec 04 Javascript
JavaScript的事件代理和委托实例分析
Mar 25 Javascript
select隐藏选中值对应的id,显示其它id的简单实现方法
Aug 25 Javascript
使用webpack搭建vue项目实现脚手架功能
Mar 15 Javascript
基于Vue 实现一个中规中矩loading组件
Apr 03 Javascript
js实现select下拉框选择
Jan 11 Javascript
vue实现简易的双向数据绑定
Dec 29 Vue.js
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
如何提高MYSQL数据库的查询统计速度 select 索引应用
2007/04/11 PHP
比较详细的关于javascript 解析json的代码
2009/12/16 Javascript
jQuery中使用了document和window哪些属性和方法小结
2011/09/13 Javascript
文字不间断滚动(上下左右)实例代码
2013/04/21 Javascript
javascript页面加载完执行事件代码
2014/02/11 Javascript
jquery实现可横向和竖向展开的动态下滑菜单效果
2015/08/24 Javascript
jQuery实现商品活动倒计时
2015/10/16 Javascript
jQuery插件jquery-barcode实现条码打印的方法
2015/11/25 Javascript
详解JavaScript的AngularJS框架中的作用域与数据绑定
2016/03/04 Javascript
dedecms页面如何获取会员状态的实例代码
2016/03/15 Javascript
javascript显示倒计时控制按钮的简单实现
2016/06/07 Javascript
原生js实现tab选项卡切换
2020/03/23 Javascript
vue父组件通过props如何向子组件传递方法详解
2017/08/16 Javascript
vue中遇到的坑之变化检测问题(数组相关)
2017/10/13 Javascript
vue init失败简单解决方法(终极版)
2017/12/22 Javascript
vue项目部署上线遇到的问题及解决方法
2018/06/10 Javascript
JS数组方法reduce的用法实例分析
2020/03/03 Javascript
理解Proxy及使用Proxy实现vue数据双向绑定操作
2020/07/18 Javascript
[43:03]LGD vs Newbee 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/19 DOTA
python实现端口转发器的方法
2015/03/13 Python
Windows下PyMongo下载及安装教程
2015/04/27 Python
python绘图方法实例入门
2015/05/19 Python
python+splinter实现12306网站刷票并自动购票流程
2018/09/25 Python
详解Numpy数组转置的三种方法T、transpose、swapaxes
2019/05/27 Python
python支付宝支付示例详解
2019/08/22 Python
Python-for循环的内部机制
2020/06/12 Python
采用专利算法搜索最廉价的机票:CheapAir
2016/09/10 全球购物
特步官方商城:Xtep
2017/03/21 全球购物
Feelunique美国:欧洲大型的在线美妆零售电商
2018/11/04 全球购物
劲霸男装广告词
2014/03/21 职场文书
幼儿园保育员责任书
2014/07/22 职场文书
加强干部作风建设整改方案
2014/10/24 职场文书
高校教师个人工作总结2014
2014/12/17 职场文书
运动会报道稿大全
2015/07/23 职场文书
2016年社区党支部公开承诺书
2016/03/25 职场文书
pytorch交叉熵损失函数的weight参数的使用
2021/05/24 Python