利用原生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的document.all函数使用示例
Dec 30 Javascript
javascript中的循环语句for语句深入理解
Apr 04 Javascript
jQuery在页面加载时动态修改图片尺寸的方法
Mar 20 Javascript
浅谈JavaScript的push(),pop(),concat()方法
Jun 03 Javascript
Avalonjs 实现简单购物车功能(实例代码)
Feb 07 Javascript
jQuery插件Echarts实现的双轴图效果示例【附demo源码下载】
Mar 04 Javascript
vue使用watch 观察路由变化,重新获取内容
Mar 08 Javascript
原生js封装自定义滚动条
Mar 24 Javascript
React组件中的this的具体使用
Feb 28 Javascript
JS/HTML5游戏常用算法之碰撞检测 像素检测算法实例详解
Dec 12 Javascript
手把手教您实现react异步加载高阶组件
Apr 07 Javascript
Vue中 axios delete请求参数操作
Aug 25 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
114啦源码(114la)不能生成地方房产和地方报刊问题4级页面0字节的解决方法
2012/01/12 PHP
php通过文件流方式复制文件的方法
2015/03/13 PHP
初识ThinkPHP控制器
2016/04/07 PHP
PHPCMS忘记后台密码的解决办法
2016/10/30 PHP
Javascript 获取链接(url)参数的方法
2009/02/15 Javascript
js 数组去重的四种实用方法
2014/09/09 Javascript
浅谈javascript中this在事件中的应用
2015/02/15 Javascript
JSON遍历方式实例总结
2015/12/07 Javascript
jQuery制作圣诞主题页面 更像是爱情影集
2016/08/10 Javascript
JavaScript实现刷新不重记的倒计时
2016/08/10 Javascript
关于动态执行代码(js的Eval)实例详解
2016/08/15 Javascript
Javascript仿京东放大镜的效果
2017/03/01 Javascript
jQuery遍历节点方法汇总(推荐)
2017/05/13 jQuery
JS使用贪心算法解决找零问题示例
2017/11/27 Javascript
重学JS之显示强制类型转换详解
2019/06/30 Javascript
更优雅的微信小程序骨架屏实现详解
2019/08/07 Javascript
Vue中通过Vue.extend动态创建实例的方法
2019/08/13 Javascript
用Python制作简单的朴素基数估计器的教程
2015/04/01 Python
Python中的XML库4Suite Server的介绍
2015/04/14 Python
对于Python的框架中一些会话程序的管理
2015/04/20 Python
Python中线程编程之threading模块的使用详解
2015/06/23 Python
Django 添加静态文件的两种实现方法(必看篇)
2017/07/14 Python
Python下使用Scrapy爬取网页内容的实例
2018/05/21 Python
HTML5中如何显示视频呢 HTML5视频播放demo
2013/06/08 HTML / CSS
美国气象仪器、花园装饰和墙壁艺术商店:Wind & Weather
2019/05/29 全球购物
全球烹饪课程的领先预订平台:Cookly
2020/01/28 全球购物
英国手工制作的现代与经典的沙发和床:Love Your Home
2020/09/26 全球购物
JPA面试常见问题
2016/11/14 面试题
中专生自荐信
2013/10/12 职场文书
新闻专业学生的自我评价
2014/02/13 职场文书
村创先争优活动总结
2014/08/28 职场文书
暖春观后感
2015/06/08 职场文书
个人落户申请书怎么写?
2019/06/28 职场文书
Python趣味挑战之教你用pygame画进度条
2021/05/31 Python
python中字符串String及其常见操作指南(方法、函数)
2022/04/06 Python
Python之matplotlib绘制折线图
2022/04/13 Python