forked from inorganik/countUp.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
countUp.coffee
144 lines (118 loc) · 3.95 KB
/
countUp.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
###
#
# countUp.js
# by @inorganik
# v 1.0.2
#
# Example:
# numAnim = new countUp "SomeElementYouWantToAnimate", 99.99, 2, 1.5
# numAnim.start()
#
###
# target = id of Html element where counting occurs
# startVal = the value you want to start at
# endVal = the value you want to arrive at
# decimals = number of decimal places in number, default 0
# duration = duration in seconds, default 2
countUp = (target, startVal, endVal, decimals, duration) ->
lastTime = 0
vendors = [
'webkit'
'moz'
'ms'
]
#toggle easing
@useEasing = true
@doc = if (typeof target == 'string') then document.getElementById target else target
@startVal = Number startVal
endVal = Number endVal
@countDown = if (startVal > endVal) then true else false
decimals = Math.max(0, decimals or 0)
@dec = Math.pow(10, decimals)
@duration = duration * 1000 or 2000
@startTime = null
@remaining = null
@frameVal = @startVal
@rAF = null
# make sure requestAnimationFrame and cancelAnimationFrame are defined
# polyfill for browsers without native support
# by Opera engineer Erik Möller
while x < vendors.length and not window.requestAnimationFrame
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
window.cancelAnimationFrame =
window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']
unless window.requestAnimationFrame
window.requestAnimationFrame = (callback, element) ->
currTime = new Date().getTime()
timeToCall = Math.max 0, 16 - (currTime - lastTime)
id = window.setTimeout(->
callback currTime + timeToCall
, timeToCall)
lastTime = currTime + timeToCall
id
unless window.cancelAnimationFrame
window.cancelAnimationFrame = (id) ->
clearTimeout id
# Robert Penner's easeOutExpo
@easeOutExpo = (t, b, c, d) ->
c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b
@count = (timestamp) ->
@startTime = timestamp if @startTime is null
@timestamp = timestamp
progress = timestamp - @startTime
# to ease or not to ease is the question
if @useEasing
if @countDown
i = @easeOutExpo progress, 0, @startVal - endVal, @duration
@frameVal = @startVal - i
else
@frameVal = @easeOutExpo(progress, @startVal, endVal - @startVal, @duration)
else
if @countDown
i = (startVal - endVal) * (progress / @duration)
@frameVal = @startVal - i
else
@frameVal = @startVal + (endVal - @startVal) * (progress / @duration)
# decimal
@frameVal = Math.round(@frameVal * @dec) / @dec
# don't go past enVal since progress can exceed duration in last grame
if @countDown
@frameVal = if (@framVal < endVal) then endVal else @frameVal
else
@frameVal = if (@framVal > endVal) then endVal else @frameVal
# formate and print value
@doc.innerHTML = @addCommas @frameVal.toFixed(decimals)
# weather to continue
if progress < @duration
@rAF = requestAnimationFrame @count
else
@callback() if @callback?
@start = (callback) ->
@callback = callback
# make sure endVal is a number
requestAnimationFrame @count unless isNaN(endVal) and isNan(startVal) isnt null
else
console.log('countUp error: startVal or endVal is not a number')
@doc.innerHTML = '--'
false
@stop = () ->
cancelAnimationFrame @rAF
@reset = () ->
cancelAnimationFrame @rAF
@doc.innerHTML = @addCommas @startVal.toFixed(decimals)
@resume = () ->
@startTime = null
@duration = @remaining
@startVal = @framVal
requestAnimationFrame @count
@addCommas = (nStr) ->
nStr += ''
x = nStr.split('.')
x1 = x[0]
x2 = if x.length > 1 then "." + x[1] else ''
rgx = /(\d+)(\d{3})/
while rgx.test(x1)
x1 = x1.replace(rgx, '$1' + ',' + '$2')
x1 + x2
# format startVal on initialization
@doc.innerHTML = @addCommas @startVal.toFixed(decimals)