利用原生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做一个小游戏平台 (一)
Dec 29 Javascript
javascript 拖放效果实现代码
Jan 22 Javascript
精心挑选的12款优秀的基于jQuery的手风琴效果插件和教程
Aug 22 Javascript
Javascript Memoizer浅析
Oct 16 Javascript
JavaScript实现当网页加载完成后执行指定函数的方法
Mar 21 Javascript
详解JavaScript的while循环的使用
Jun 03 Javascript
微信小程序 摇一摇抽奖简单实例实现代码
Jan 09 Javascript
解决layui前端框架 form表单,table表等内置控件不显示的问题
Aug 19 Javascript
vue-cli项目修改文件热重载失效的解决方法
Sep 19 Javascript
使用vue2.6实现抖音【时间轮盘】屏保效果附源码
Apr 24 Javascript
解决ant-design-vue中menu菜单无法默认展开的问题
Oct 31 Javascript
详解vite+ts快速搭建vue3项目以及介绍相关特性
Feb 25 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
第十二节 类的自动加载 [12]
2006/10/09 PHP
浅析echo(),print(),print_r(),return之间的区别
2013/11/27 PHP
zf框架的数据库追踪器使用示例
2014/03/13 PHP
php实现屏蔽掉黑帽SEO的搜索关键字
2015/04/15 PHP
PHPCMS忘记后台密码的解决办法
2016/10/30 PHP
php curl上传、下载、https登陆实现代码
2017/07/23 PHP
Thinkphp5框架使用validate实现验证功能的方法
2019/08/27 PHP
30个让人兴奋的视差滚动(Parallax Scrolling)效果网站
2012/03/04 Javascript
JS中操作JSON总结
2020/12/06 Javascript
javascript解析json数据的3种方式
2014/05/08 Javascript
AngularJS入门教程(零):引导程序
2014/12/06 Javascript
js实现常见的工具条效果
2017/03/02 Javascript
Bootstrap模态框插件使用详解
2017/05/11 Javascript
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
2017/07/11 Javascript
浅谈vue项目如何打包扔向服务器
2018/05/08 Javascript
微信运维交互机器人的示例代码
2018/11/12 Javascript
Vue 通过公共字段,拼接两个对象数组的实例
2019/11/07 Javascript
微信小程序实现滚动加载更多的代码
2019/12/06 Javascript
[01:02:34]TFT vs VGJ.T Supermajor 败者组 BO3 第二场 6.5
2018/06/06 DOTA
Python的包管理器pip更换软件源的方法详解
2016/06/20 Python
python将字符串以utf-8格式保存在txt文件中的方法
2018/10/30 Python
Python修改列表值问题解决方案
2020/03/06 Python
Python HTTP下载文件并显示下载进度条功能的实现
2020/04/02 Python
简单了解如何封装自己的Python包
2020/07/08 Python
python集合能干吗
2020/07/19 Python
python+openCV对视频进行截取的实现
2020/11/27 Python
cosme官方海外旗舰店:日本最大化妆品和美容产品的综合口碑网站
2017/01/18 全球购物
自荐信结尾
2013/10/27 职场文书
生物技术研究生自荐信
2013/11/12 职场文书
咖啡馆创业计划书
2014/01/26 职场文书
学习型家庭事迹材料
2014/12/20 职场文书
小学班主任评语
2014/12/29 职场文书
生日宴会家属答谢词
2015/09/29 职场文书
2015新员工工作总结范文
2015/10/15 职场文书
2016年青少年禁毒宣传教育活动总结(学校)
2016/04/05 职场文书
cypress测试本地web应用
2022/06/01 Javascript