利用原生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 相关文章推荐
jQuery实现密保互斥问题解决方案
Aug 16 Javascript
JS+CSS模拟可以无刷新显示内容的留言板实例
Mar 03 Javascript
浅谈angularJS 作用域
Jul 05 Javascript
JavaScript中函数(Function)的apply与call理解
Jul 08 Javascript
jQuery实现背景弹性滚动的导航效果
Jun 01 Javascript
JS实现滑动门效果的方法详解
Dec 19 Javascript
浅谈javascript的闭包
Jan 23 Javascript
react native实现往服务器上传网络图片的实例
Aug 07 Javascript
seajs实现强制刷新本地缓存的方法分析
Oct 16 Javascript
JS跳转手机站url的若干注意事项
Oct 18 Javascript
对layui中table组件工具栏的使用详解
Sep 19 Javascript
jQuery 函数实例分析【函数声明、函数表达式、匿名函数等】
May 19 jQuery
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
音乐朗读剧《MARS RED》2021年TV动画化决定!
2020/03/06 日漫
深入Memcache的Session数据的多服务器共享详解
2013/06/13 PHP
浅析51个PHP处理字符串的函数
2013/08/02 PHP
跟着Jquery API学Jquery之一 选择器
2010/04/07 Javascript
JavaScript随机排序(随即出牌)
2010/09/17 Javascript
7款吸引人眼球的jQuery/CSS3特效实例分享
2013/04/25 Javascript
怎么选择Javascript框架(Javascript Framework)
2013/11/22 Javascript
js的alert样式如何更改如背景颜色
2014/01/22 Javascript
jquery.Ajax()方法调用Asp.Net后台的方法解析
2014/02/13 Javascript
js事件监听机制(事件捕获)总结
2014/08/08 Javascript
node.js中的url.format方法使用说明
2014/12/10 Javascript
JavaScript实现数字数组按照倒序排列的方法
2015/04/06 Javascript
基于javascript代码实现通过点击图片显示原图片
2015/11/29 Javascript
多种方式实现js图片预览
2016/12/12 Javascript
Node.js数据库操作之查询MySQL数据库(二)
2017/03/04 Javascript
jQuery Validate 相关参数及常用的自定义验证规则
2017/03/06 Javascript
微信小程序 在线支付功能的实现
2017/03/14 Javascript
关于meta viewport中target-densitydpi属性详解(推荐)
2017/08/18 Javascript
纯js实现画一棵树的示例
2017/09/05 Javascript
在Vant的基础上封装下拉日期控件的代码示例
2018/12/05 Javascript
vue实现codemirror代码编辑器中的SQL代码格式化功能
2019/08/27 Javascript
仿照Element-ui实现一个简易的$message方法
2020/09/14 Javascript
Python画图学习入门教程
2016/07/01 Python
python实现在函数中修改变量值的方法
2019/07/16 Python
基于python实现学生信息管理系统
2019/11/22 Python
给 TensorFlow 变量进行赋值的方式
2020/02/10 Python
python目标检测给图画框,bbox画到图上并保存案例
2020/03/10 Python
Python semaphore evevt生产者消费者模型原理解析
2020/03/18 Python
Python celery原理及运行流程解析
2020/06/13 Python
html5服务器推送_动力节点Java学院整理
2017/07/12 HTML / CSS
阿联酋团购网站:Groupon阿联酋
2016/10/14 全球购物
美国购买和销售礼品卡平台:Raise
2017/01/13 全球购物
工作失职检讨书500字
2014/10/17 职场文书
党的群众路线教育实践活动个人整改落实情况汇报
2014/10/28 职场文书
人与自然的观后感
2015/06/18 职场文书
七年级作文之雪景
2019/11/18 职场文书