利用原生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去掉字符串里的所有空格
Feb 08 Javascript
List the UTC Time on a Computer
Jun 11 Javascript
json简单介绍
Jun 10 Javascript
javascript 构建一个xmlhttp对象池合理创建和使用xmlhttp对象
Jan 15 Javascript
js获取本机的外网/广域网ip地址完整源码
Aug 12 Javascript
js获取元素下的第一级子元素的方法(推荐)
Mar 05 Javascript
浅谈Vuex的状态管理(全家桶)
Nov 04 Javascript
代码详解JS操作剪贴板
Feb 11 Javascript
vue 路由页面之间实现用手指进行滑动的方法
Feb 23 Javascript
vue slot与传参实例代码讲解
Apr 28 Javascript
Vue表单之v-model绑定下拉列表功能
May 14 Javascript
Vue.js 中的实用工具方法【推荐】
Jul 04 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
解析array splice的移除数组中指定键的值,返回一个新的数组
2013/07/02 PHP
php读取富文本的时p标签会出现红线是怎么回事
2014/05/13 PHP
Zend Framework页面缓存实例
2014/06/25 PHP
laravel 数据验证规则详解
2019/10/23 PHP
纯js实现的论坛常用的运行代码的效果
2008/07/15 Javascript
JS 创建对象(常见的几种方法)
2008/11/03 Javascript
JQuery实现用户名无刷新验证的小例子
2013/03/22 Javascript
原生JavaScript实现连连看游戏(附源码)
2013/11/05 Javascript
jquery实现点击弹出层效果的简单实例
2014/03/03 Javascript
当前流行的JavaScript代码风格指南
2014/09/10 Javascript
Javascript的setTimeout()使用闭包特性时需要注意的问题
2014/09/23 Javascript
vue.js入门教程之基础语法小结
2016/09/01 Javascript
vue拦截器Vue.http.interceptors.push使用详解
2017/04/22 Javascript
Angular将填入表单的数据渲染到表格的方法
2017/09/22 Javascript
Vue表单类的父子组件数据传递示例
2018/05/03 Javascript
vue mounted组件的使用
2018/06/18 Javascript
vue实现底部菜单功能
2018/07/24 Javascript
微信小程序冒泡事件及其阻止方法实例分析
2018/12/06 Javascript
Vue3.0的优化总结
2020/10/16 Javascript
nestjs返回给前端数据格式的封装实现
2021/02/22 Javascript
[04:51]TI10典藏宝瓶Ⅱ外观视频展示
2020/08/15 DOTA
Python提取网页中超链接的方法
2016/09/18 Python
Python 备份程序代码实现
2017/03/06 Python
Numpy中矩阵matrix读取一列的方法及数组和矩阵的相互转换实例
2018/07/02 Python
Python 3.8 新功能全解
2019/07/25 Python
Pytorch加载部分预训练模型的参数实例
2019/08/18 Python
pycharm中import呈现灰色原因的解决方法
2020/03/04 Python
python获取栅格点和面值的实现
2020/03/10 Python
django配置app中的静态文件步骤
2020/03/27 Python
粗加工管理制度
2014/02/04 职场文书
2014年行政执法工作总结
2014/12/11 职场文书
五年级下册复习计划
2015/01/19 职场文书
换届选举主持词
2015/07/03 职场文书
少先队中队工作总结
2015/08/14 职场文书
聊聊基于pytorch实现Resnet对本地数据集的训练问题
2022/03/25 Python
Github 使用python对copilot做些简单使用测试
2022/04/14 Python