PageSourceSearch

https://www.sogaworks.cn/portal/libs/countup.js

js sogaworks.cn collected 2026-10-09 22:50:52 UTC 7,162 bytes, 196 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.