countUp.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. countUp.js
  3. by @inorganik
  4. */
  5. // target = id of html element or var of previously selected html element where counting occurs
  6. // startVal = the value you want to begin at
  7. // endVal = the value you want to arrive at
  8. // decimals = number of decimal places, default 0
  9. // duration = duration of animation in seconds, default 2
  10. // options = optional object of options (see below)
  11. var CountUp = function(target, startVal, endVal, decimals, duration, options) {
  12. // make sure requestAnimationFrame and cancelAnimationFrame are defined
  13. // polyfill for browsers without native support
  14. // by Opera engineer Erik Möller
  15. var lastTime = 0;
  16. var vendors = ['webkit', 'moz', 'ms', 'o'];
  17. for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
  18. window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
  19. window.cancelAnimationFrame =
  20. window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
  21. }
  22. if (!window.requestAnimationFrame) {
  23. window.requestAnimationFrame = function(callback, element) {
  24. var currTime = new Date().getTime();
  25. var timeToCall = Math.max(0, 16 - (currTime - lastTime));
  26. var id = window.setTimeout(function() { callback(currTime + timeToCall); },
  27. timeToCall);
  28. lastTime = currTime + timeToCall;
  29. return id;
  30. };
  31. }
  32. if (!window.cancelAnimationFrame) {
  33. window.cancelAnimationFrame = function(id) {
  34. clearTimeout(id);
  35. };
  36. }
  37. var self = this;
  38. // default options
  39. self.options = {
  40. useEasing : true, // toggle easing
  41. useGrouping : true, // 1,000,000 vs 1000000
  42. separator : ',', // character to use as a separator
  43. decimal : '.', // character to use as a decimal
  44. easingFn: null, // optional custom easing closure function, default is Robert Penner's easeOutExpo
  45. formattingFn: null // optional custom formatting function, default is self.formatNumber below
  46. };
  47. // extend default options with passed options object
  48. for (var key in options) {
  49. if (options.hasOwnProperty(key)) {
  50. self.options[key] = options[key];
  51. }
  52. }
  53. if (self.options.separator === '') { self.options.useGrouping = false; }
  54. if (!self.options.prefix) self.options.prefix = '';
  55. if (!self.options.suffix) self.options.suffix = '';
  56. self.d = (typeof target === 'string') ? document.getElementById(target) : target;
  57. self.startVal = Number(startVal);
  58. self.endVal = Number(endVal);
  59. self.countDown = (self.startVal > self.endVal);
  60. self.frameVal = self.startVal;
  61. self.decimals = Math.max(0, decimals || 0);
  62. self.dec = Math.pow(10, self.decimals);
  63. self.duration = Number(duration) * 1000 || 2000;
  64. self.formatNumber = function(nStr) {
  65. nStr = nStr.toFixed(self.decimals);
  66. nStr += '';
  67. var x, x1, x2, rgx;
  68. x = nStr.split('.');
  69. x1 = x[0];
  70. x2 = x.length > 1 ? self.options.decimal + x[1] : '';
  71. rgx = /(\d+)(\d{3})/;
  72. if (self.options.useGrouping) {
  73. while (rgx.test(x1)) {
  74. x1 = x1.replace(rgx, '$1' + self.options.separator + '$2');
  75. }
  76. }
  77. return self.options.prefix + x1 + x2 + self.options.suffix;
  78. };
  79. // Robert Penner's easeOutExpo
  80. self.easeOutExpo = function(t, b, c, d) {
  81. return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
  82. };
  83. self.easingFn = self.options.easingFn ? self.options.easingFn : self.easeOutExpo;
  84. self.formattingFn = self.options.formattingFn ? self.options.formattingFn : self.formatNumber;
  85. self.version = function () { return '1.7.1'; };
  86. // Print value to target
  87. self.printValue = function(value) {
  88. var result = self.formattingFn(value);
  89. if (self.d.tagName === 'INPUT') {
  90. this.d.value = result;
  91. }
  92. else if (self.d.tagName === 'text' || self.d.tagName === 'tspan') {
  93. this.d.textContent = result;
  94. }
  95. else {
  96. this.d.innerHTML = result;
  97. }
  98. };
  99. self.count = function(timestamp) {
  100. if (!self.startTime) { self.startTime = timestamp; }
  101. self.timestamp = timestamp;
  102. var progress = timestamp - self.startTime;
  103. self.remaining = self.duration - progress;
  104. // to ease or not to ease
  105. if (self.options.useEasing) {
  106. if (self.countDown) {
  107. self.frameVal = self.startVal - self.easingFn(progress, 0, self.startVal - self.endVal, self.duration);
  108. } else {
  109. self.frameVal = self.easingFn(progress, self.startVal, self.endVal - self.startVal, self.duration);
  110. }
  111. } else {
  112. if (self.countDown) {
  113. self.frameVal = self.startVal - ((self.startVal - self.endVal) * (progress / self.duration));
  114. } else {
  115. self.frameVal = self.startVal + (self.endVal - self.startVal) * (progress / self.duration);
  116. }
  117. }
  118. // don't go past endVal since progress can exceed duration in the last frame
  119. if (self.countDown) {
  120. self.frameVal = (self.frameVal < self.endVal) ? self.endVal : self.frameVal;
  121. } else {
  122. self.frameVal = (self.frameVal > self.endVal) ? self.endVal : self.frameVal;
  123. }
  124. // decimal
  125. self.frameVal = Math.round(self.frameVal*self.dec)/self.dec;
  126. // format and print value
  127. self.printValue(self.frameVal);
  128. // whether to continue
  129. if (progress < self.duration) {
  130. self.rAF = requestAnimationFrame(self.count);
  131. } else {
  132. if (self.callback) { self.callback(); }
  133. }
  134. };
  135. // start your animation
  136. self.start = function(callback) {
  137. self.callback = callback;
  138. self.rAF = requestAnimationFrame(self.count);
  139. return false;
  140. };
  141. // toggles pause/resume animation
  142. self.pauseResume = function() {
  143. if (!self.paused) {
  144. self.paused = true;
  145. cancelAnimationFrame(self.rAF);
  146. } else {
  147. self.paused = false;
  148. delete self.startTime;
  149. self.duration = self.remaining;
  150. self.startVal = self.frameVal;
  151. requestAnimationFrame(self.count);
  152. }
  153. };
  154. // reset to startVal so animation can be run again
  155. self.reset = function() {
  156. self.paused = false;
  157. delete self.startTime;
  158. self.startVal = startVal;
  159. cancelAnimationFrame(self.rAF);
  160. self.printValue(self.startVal);
  161. };
  162. // pass a new endVal and start animation
  163. self.update = function (newEndVal) {
  164. cancelAnimationFrame(self.rAF);
  165. self.paused = false;
  166. delete self.startTime;
  167. self.startVal = self.frameVal;
  168. self.endVal = Number(newEndVal);
  169. self.countDown = (self.startVal > self.endVal);
  170. self.rAF = requestAnimationFrame(self.count);
  171. };
  172. // format startVal on initialization
  173. self.printValue(self.startVal);
  174. };