diff --git a/README.md b/README.md index 8f2897b..03345d6 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ interface CountUpOptions { numerals?: string[]; // numeral glyph substitution enableScrollSpy?: boolean; // start animation when target is in view scrollSpyDelay?: number; // delay (ms) after target comes into view + scrollSpyOnce?: boolean; // run only once } ``` diff --git a/dist/countUp.d.ts b/dist/countUp.d.ts index fb79c38..3b3611a 100644 --- a/dist/countUp.d.ts +++ b/dist/countUp.d.ts @@ -15,6 +15,7 @@ export interface CountUpOptions { numerals?: string[]; enableScrollSpy?: boolean; scrollSpyDelay?: number; + scrollSpyOnce?: boolean; } export declare class CountUp { private endVal; @@ -36,6 +37,7 @@ export declare class CountUp { duration: number; paused: boolean; frameVal: number; + once: boolean; constructor(target: string | HTMLElement | HTMLInputElement, endVal: number, options?: CountUpOptions); handleScroll(self: CountUp): void; private determineDirectionAndSmartEasing; diff --git a/dist/countUp.js b/dist/countUp.js index 6f113c1..ed99e2b 100644 --- a/dist/countUp.js +++ b/dist/countUp.js @@ -30,6 +30,7 @@ var CountUp = /** @class */ (function () { suffix: '', enableScrollSpy: false, scrollSpyDelay: 200, + scrollSpyOnce: false, }; this.finalEndVal = null; // for smart easing this.useEasing = true; @@ -37,6 +38,7 @@ var CountUp = /** @class */ (function () { this.error = ''; this.startVal = 0; this.paused = true; + this.once = false; this.count = function (timestamp) { if (!_this.startTime) { _this.startTime = timestamp; @@ -153,7 +155,7 @@ var CountUp = /** @class */ (function () { } } CountUp.prototype.handleScroll = function (self) { - if (!self || !window) + if (!self || !window || self.once) return; var bottomOfScroll = window.innerHeight + window.scrollY; var bottomOfEl = self.el.offsetTop + self.el.offsetHeight; @@ -161,6 +163,8 @@ var CountUp = /** @class */ (function () { // in view self.paused = false; setTimeout(function () { return self.start(); }, self.options.scrollSpyDelay); + if (self.options.scrollSpyOnce) + self.once = true; } else if (window.scrollY > bottomOfEl && !self.paused) { // scrolled past diff --git a/dist/countUp.min.js b/dist/countUp.min.js index 91025b6..056f821 100644 --- a/dist/countUp.min.js +++ b/dist/countUp.min.js @@ -1 +1 @@ -var __assign=this&&this.__assign||function(){return(__assign=Object.assign||function(t){for(var i,a=1,n=arguments.length;an.endVal?n.endVal:n.frameVal,n.frameVal=Number(n.frameVal.toFixed(n.options.decimalPlaces)),n.printValue(n.frameVal),i1?n.options.decimal+o[1]:"",n.options.useGrouping){e="";for(var l=0,h=a.length;lwindow.scrollY&&t.paused?(t.paused=!1,setTimeout(function(){return t.start()},t.options.scrollSpyDelay)):window.scrollY>a&&!t.paused&&t.reset()}},t.prototype.determineDirectionAndSmartEasing=function(){var t=this.finalEndVal?this.finalEndVal:this.endVal;this.countDown=this.startVal>t;var i=t-this.startVal;if(Math.abs(i)>this.options.smartEasingThreshold){this.finalEndVal=t;var a=this.countDown?1:-1;this.endVal=t+a*this.options.smartEasingAmount,this.duration=this.duration/2}else this.endVal=t,this.finalEndVal=null;this.finalEndVal?this.useEasing=!1:this.useEasing=this.options.useEasing},t.prototype.start=function(t){this.error||(this.callback=t,this.duration>0?(this.determineDirectionAndSmartEasing(),this.paused=!1,this.rAF=requestAnimationFrame(this.count)):this.printValue(this.endVal))},t.prototype.pauseResume=function(){this.paused?(this.startTime=null,this.duration=this.remaining,this.startVal=this.frameVal,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count)):cancelAnimationFrame(this.rAF),this.paused=!this.paused},t.prototype.reset=function(){cancelAnimationFrame(this.rAF),this.paused=!0,this.resetDuration(),this.startVal=this.validateValue(this.options.startVal),this.frameVal=this.startVal,this.printValue(this.startVal)},t.prototype.update=function(t){cancelAnimationFrame(this.rAF),this.startTime=null,this.endVal=this.validateValue(t),this.endVal!==this.frameVal&&(this.startVal=this.frameVal,this.finalEndVal||this.resetDuration(),this.finalEndVal=null,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count))},t.prototype.printValue=function(t){var i=this.formattingFn(t);"INPUT"===this.el.tagName?this.el.value=i:"text"===this.el.tagName||"tspan"===this.el.tagName?this.el.textContent=i:this.el.innerHTML=i},t.prototype.ensureNumber=function(t){return"number"==typeof t&&!isNaN(t)},t.prototype.validateValue=function(t){var i=Number(t);return this.ensureNumber(i)?i:(this.error="[CountUp] invalid start or end value: ".concat(t),null)},t.prototype.resetDuration=function(){this.startTime=null,this.duration=1e3*Number(this.options.duration),this.remaining=this.duration},t}();export{CountUp}; \ No newline at end of file +var __assign=this&&this.__assign||function(){return(__assign=Object.assign||function(t){for(var i,n=1,a=arguments.length;na.endVal?a.endVal:a.frameVal,a.frameVal=Number(a.frameVal.toFixed(a.options.decimalPlaces)),a.printValue(a.frameVal),i1?a.options.decimal+o[1]:"",a.options.useGrouping){e="";for(var l=0,h=n.length;lwindow.scrollY&&t.paused?(t.paused=!1,setTimeout(function(){return t.start()},t.options.scrollSpyDelay),t.options.scrollSpyOnce&&(t.once=!0)):window.scrollY>n&&!t.paused&&t.reset()}},t.prototype.determineDirectionAndSmartEasing=function(){var t=this.finalEndVal?this.finalEndVal:this.endVal;this.countDown=this.startVal>t;var i=t-this.startVal;if(Math.abs(i)>this.options.smartEasingThreshold){this.finalEndVal=t;var n=this.countDown?1:-1;this.endVal=t+n*this.options.smartEasingAmount,this.duration=this.duration/2}else this.endVal=t,this.finalEndVal=null;this.finalEndVal?this.useEasing=!1:this.useEasing=this.options.useEasing},t.prototype.start=function(t){this.error||(this.callback=t,this.duration>0?(this.determineDirectionAndSmartEasing(),this.paused=!1,this.rAF=requestAnimationFrame(this.count)):this.printValue(this.endVal))},t.prototype.pauseResume=function(){this.paused?(this.startTime=null,this.duration=this.remaining,this.startVal=this.frameVal,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count)):cancelAnimationFrame(this.rAF),this.paused=!this.paused},t.prototype.reset=function(){cancelAnimationFrame(this.rAF),this.paused=!0,this.resetDuration(),this.startVal=this.validateValue(this.options.startVal),this.frameVal=this.startVal,this.printValue(this.startVal)},t.prototype.update=function(t){cancelAnimationFrame(this.rAF),this.startTime=null,this.endVal=this.validateValue(t),this.endVal!==this.frameVal&&(this.startVal=this.frameVal,this.finalEndVal||this.resetDuration(),this.finalEndVal=null,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count))},t.prototype.printValue=function(t){var i=this.formattingFn(t);"INPUT"===this.el.tagName?this.el.value=i:"text"===this.el.tagName||"tspan"===this.el.tagName?this.el.textContent=i:this.el.innerHTML=i},t.prototype.ensureNumber=function(t){return"number"==typeof t&&!isNaN(t)},t.prototype.validateValue=function(t){var i=Number(t);return this.ensureNumber(i)?i:(this.error="[CountUp] invalid start or end value: ".concat(t),null)},t.prototype.resetDuration=function(){this.startTime=null,this.duration=1e3*Number(this.options.duration),this.remaining=this.duration},t}();export{CountUp}; \ No newline at end of file diff --git a/dist/countUp.umd.js b/dist/countUp.umd.js index c331bf2..7080212 100644 --- a/dist/countUp.umd.js +++ b/dist/countUp.umd.js @@ -36,6 +36,7 @@ suffix: '', enableScrollSpy: false, scrollSpyDelay: 200, + scrollSpyOnce: false, }; this.finalEndVal = null; // for smart easing this.useEasing = true; @@ -43,6 +44,7 @@ this.error = ''; this.startVal = 0; this.paused = true; + this.once = false; this.count = function (timestamp) { if (!_this.startTime) { _this.startTime = timestamp; @@ -159,7 +161,7 @@ } } CountUp.prototype.handleScroll = function (self) { - if (!self || !window) + if (!self || !window || self.once) return; var bottomOfScroll = window.innerHeight + window.scrollY; var bottomOfEl = self.el.offsetTop + self.el.offsetHeight; @@ -167,6 +169,8 @@ // in view self.paused = false; setTimeout(function () { return self.start(); }, self.options.scrollSpyDelay); + if (self.options.scrollSpyOnce) + self.once = true; } else if (window.scrollY > bottomOfEl && !self.paused) { // scrolled past diff --git a/dist/countUp.withPolyfill.min.js b/dist/countUp.withPolyfill.min.js index 58b520b..b69884c 100644 --- a/dist/countUp.withPolyfill.min.js +++ b/dist/countUp.withPolyfill.min.js @@ -1 +1 @@ -!function(){for(var t=0,i=["webkit","moz","ms","o"],n=0;na.endVal?a.endVal:a.frameVal,a.frameVal=Number(a.frameVal.toFixed(a.options.decimalPlaces)),a.printValue(a.frameVal),i1?a.options.decimal+o[1]:"",a.options.useGrouping){e="";for(var l=0,u=n.length;lwindow.scrollY&&t.paused?(t.paused=!1,setTimeout(function(){return t.start()},t.options.scrollSpyDelay)):window.scrollY>n&&!t.paused&&t.reset()}},t.prototype.determineDirectionAndSmartEasing=function(){var t=this.finalEndVal?this.finalEndVal:this.endVal;this.countDown=this.startVal>t;var i=t-this.startVal;if(Math.abs(i)>this.options.smartEasingThreshold){this.finalEndVal=t;var n=this.countDown?1:-1;this.endVal=t+n*this.options.smartEasingAmount,this.duration=this.duration/2}else this.endVal=t,this.finalEndVal=null;this.finalEndVal?this.useEasing=!1:this.useEasing=this.options.useEasing},t.prototype.start=function(t){this.error||(this.callback=t,this.duration>0?(this.determineDirectionAndSmartEasing(),this.paused=!1,this.rAF=requestAnimationFrame(this.count)):this.printValue(this.endVal))},t.prototype.pauseResume=function(){this.paused?(this.startTime=null,this.duration=this.remaining,this.startVal=this.frameVal,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count)):cancelAnimationFrame(this.rAF),this.paused=!this.paused},t.prototype.reset=function(){cancelAnimationFrame(this.rAF),this.paused=!0,this.resetDuration(),this.startVal=this.validateValue(this.options.startVal),this.frameVal=this.startVal,this.printValue(this.startVal)},t.prototype.update=function(t){cancelAnimationFrame(this.rAF),this.startTime=null,this.endVal=this.validateValue(t),this.endVal!==this.frameVal&&(this.startVal=this.frameVal,this.finalEndVal||this.resetDuration(),this.finalEndVal=null,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count))},t.prototype.printValue=function(t){var i=this.formattingFn(t);"INPUT"===this.el.tagName?this.el.value=i:"text"===this.el.tagName||"tspan"===this.el.tagName?this.el.textContent=i:this.el.innerHTML=i},t.prototype.ensureNumber=function(t){return"number"==typeof t&&!isNaN(t)},t.prototype.validateValue=function(t){var i=Number(t);return this.ensureNumber(i)?i:(this.error="[CountUp] invalid start or end value: ".concat(t),null)},t.prototype.resetDuration=function(){this.startTime=null,this.duration=1e3*Number(this.options.duration),this.remaining=this.duration},t}();export{CountUp}; \ No newline at end of file +!function(){for(var t=0,i=["webkit","moz","ms","o"],n=0;na.endVal?a.endVal:a.frameVal,a.frameVal=Number(a.frameVal.toFixed(a.options.decimalPlaces)),a.printValue(a.frameVal),i1?a.options.decimal+r[1]:"",a.options.useGrouping){e="";for(var l=0,u=n.length;lwindow.scrollY&&t.paused?(t.paused=!1,setTimeout(function(){return t.start()},t.options.scrollSpyDelay),t.options.scrollSpyOnce&&(t.once=!0)):window.scrollY>n&&!t.paused&&t.reset()}},t.prototype.determineDirectionAndSmartEasing=function(){var t=this.finalEndVal?this.finalEndVal:this.endVal;this.countDown=this.startVal>t;var i=t-this.startVal;if(Math.abs(i)>this.options.smartEasingThreshold){this.finalEndVal=t;var n=this.countDown?1:-1;this.endVal=t+n*this.options.smartEasingAmount,this.duration=this.duration/2}else this.endVal=t,this.finalEndVal=null;this.finalEndVal?this.useEasing=!1:this.useEasing=this.options.useEasing},t.prototype.start=function(t){this.error||(this.callback=t,this.duration>0?(this.determineDirectionAndSmartEasing(),this.paused=!1,this.rAF=requestAnimationFrame(this.count)):this.printValue(this.endVal))},t.prototype.pauseResume=function(){this.paused?(this.startTime=null,this.duration=this.remaining,this.startVal=this.frameVal,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count)):cancelAnimationFrame(this.rAF),this.paused=!this.paused},t.prototype.reset=function(){cancelAnimationFrame(this.rAF),this.paused=!0,this.resetDuration(),this.startVal=this.validateValue(this.options.startVal),this.frameVal=this.startVal,this.printValue(this.startVal)},t.prototype.update=function(t){cancelAnimationFrame(this.rAF),this.startTime=null,this.endVal=this.validateValue(t),this.endVal!==this.frameVal&&(this.startVal=this.frameVal,this.finalEndVal||this.resetDuration(),this.finalEndVal=null,this.determineDirectionAndSmartEasing(),this.rAF=requestAnimationFrame(this.count))},t.prototype.printValue=function(t){var i=this.formattingFn(t);"INPUT"===this.el.tagName?this.el.value=i:"text"===this.el.tagName||"tspan"===this.el.tagName?this.el.textContent=i:this.el.innerHTML=i},t.prototype.ensureNumber=function(t){return"number"==typeof t&&!isNaN(t)},t.prototype.validateValue=function(t){var i=Number(t);return this.ensureNumber(i)?i:(this.error="[CountUp] invalid start or end value: ".concat(t),null)},t.prototype.resetDuration=function(){this.startTime=null,this.duration=1e3*Number(this.options.duration),this.remaining=this.duration},t}();export{CountUp}; \ No newline at end of file diff --git a/src/countUp.ts b/src/countUp.ts index dc6aeed..0c1439d 100644 --- a/src/countUp.ts +++ b/src/countUp.ts @@ -16,6 +16,7 @@ export interface CountUpOptions { // (default) numerals?: string[]; // numeral glyph substitution enableScrollSpy?: boolean; // start animation when target is in view scrollSpyDelay?: number; // delay (ms) after target comes into view + scrollSpyOnce?: boolean; // run only once } // playground: stackblitz.com/edit/countup-typescript @@ -36,6 +37,7 @@ export class CountUp { suffix: '', enableScrollSpy: false, scrollSpyDelay: 200, + scrollSpyOnce: false, }; private el: HTMLElement | HTMLInputElement; private rAF: any; @@ -52,6 +54,7 @@ export class CountUp { duration: number; paused = true; frameVal: number; + once = false; constructor( target: string | HTMLElement | HTMLInputElement, @@ -101,13 +104,15 @@ export class CountUp { } handleScroll(self: CountUp): void { - if (!self || !window) return; + if (!self || !window || self.once) return; const bottomOfScroll = window.innerHeight + window.scrollY; const bottomOfEl = self.el.offsetTop + self.el.offsetHeight; if (bottomOfEl < bottomOfScroll && bottomOfEl > window.scrollY && self.paused) { // in view self.paused = false; setTimeout(() => self.start(), self.options.scrollSpyDelay); + if (self.options.scrollSpyOnce) + self.once = true; } else if ( window.scrollY > bottomOfEl && !self.paused) { // scrolled past self.reset();