利用原生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中eval()函数和trim()去掉字符串左右空格应用
Feb 02 Javascript
分享JavaScript获取网页关闭与取消关闭的事件
Dec 13 Javascript
javascript实现显示和隐藏div方法汇总
Aug 14 Javascript
详解Javascript中new()到底做了些什么?
Mar 29 Javascript
vue实现未登录跳转到登录页面的方法
Jul 17 Javascript
angularjs 动态从后台获取下拉框的值方法
Aug 13 Javascript
js拖动滑块和点击水波纹效果实例代码
Oct 16 Javascript
微信小程序实现签字功能
Dec 23 Javascript
vue-socket.io跨域问题有效解决方法
Feb 11 Javascript
vue cli4下环境变量和模式示例详解
Apr 09 Javascript
基于JS实现计算24点算法代码实例解析
Jul 23 Javascript
js实现删除json中指定的元素
Sep 22 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
Laravel框架中Blade模板的用法示例
2017/08/30 PHP
javascript据option的value值快速设定初始的selected选项
2007/08/13 Javascript
jQuery入门知识简介
2010/03/04 Javascript
11个用于提高排版水平的基于jquery的文字效果插件
2012/09/14 Javascript
jQuery中;function($,undefined) 前面的分号的用处
2014/12/17 Javascript
JavaScript中的Reflect对象详解(ES6新特性)
2016/07/22 Javascript
Node.js websocket使用socket.io库实现实时聊天室
2017/02/20 Javascript
详解Node.js项目APM监控之New Relic
2017/05/12 Javascript
详解如何用模块化的方式写vuejs
2017/12/16 Javascript
详解mpvue中使用vant时需要注意的onChange事件的坑
2019/05/16 Javascript
JavaScript函数式编程(Functional Programming)箭头函数(Arrow functions)用法分析
2019/05/22 Javascript
个人小程序接入支付解决方案
2019/05/23 Javascript
jquery+ajax实现上传图片并显示上传进度功能【附php后台接收】
2019/06/06 jQuery
微信小程序身份证验证方法实现详解
2019/06/28 Javascript
微信小程序自定义导航栏(模板化)
2019/11/15 Javascript
JavaScript实现移动端带transition动画的轮播效果
2020/03/24 Javascript
python strip()函数 介绍
2013/05/24 Python
Python实现二叉堆
2016/02/03 Python
python3判断url链接是否为404的方法
2018/08/10 Python
python可视化爬虫界面之天气查询
2019/07/03 Python
讲解Python3中NumPy数组寻找特定元素下标的两种方法
2019/08/04 Python
python 使用递归回溯完美解决八皇后的问题
2020/02/26 Python
HTML5 canvas实现雪花飘落特效
2016/03/08 HTML / CSS
德国化妆品和天然化妆品网上商店:kosmetikfuchs.de
2017/06/09 全球购物
Waterford英国官方网站:世界上最受欢迎的优质水晶品牌
2019/08/17 全球购物
Perfume’s Club澳大利亚官网:西班牙领先的在线美容店
2021/02/01 全球购物
PHP如何与mysql建立链接
2013/05/05 面试题
微型企业创业投资计划书
2014/01/10 职场文书
美德好少年主要事迹
2014/01/29 职场文书
家教广告词
2014/03/19 职场文书
餐饮投资计划书
2014/04/25 职场文书
设计专业毕业生求职信
2014/06/25 职场文书
乡镇一岗双责责任书
2015/01/29 职场文书
奖励通知
2015/04/22 职场文书
2015年“公民道德宣传日”活动方案
2015/05/06 职场文书
歼十出击观后感
2015/06/11 职场文书