├── .editorconfig ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── bs-config.json ├── example ├── app │ ├── app.component.spec.ts │ ├── app.component.ts │ └── app.module.ts ├── index.html ├── main.ts ├── styles.css └── tsconfig.json ├── index.ts ├── package.json ├── src ├── counto.directive.ts └── counto.module.ts ├── tests └── .gitkeep └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [*.{ts,json}] 8 | charset = utf-8 9 | indent_style = space 10 | indent_size = 4 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | node_modules 3 | *.js 4 | *.js.map 5 | *.d.ts 6 | package-lock.json 7 | *.metadata.json 8 | *.ngsummary.json 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *~ 2 | node_modules 3 | *.ts 4 | !*.d.ts 5 | package-lock.json 6 | *.ngFactory.ts 7 | *.ngsummary.json 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Igor Zupet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular2-counto 2 | 3 | Angular 5 package for nice count animations 4 | 5 | ## Installation 6 | ``` 7 | npm install angular2-counto --save 8 | ``` 9 | 10 | ### SystemJS 11 | ``` 12 | var map = { 13 | 'angular2-counto': 'node_modules/angular2-counto/src' 14 | }; 15 | 16 | var packages = { 17 | 'angular2-counto': { main: 'counto.module.js', defaultExtension: 'js' } 18 | }; 19 | ``` 20 | 21 | ### Angular-CLI 22 | Just import module as below: 23 | 24 | 25 | ``` 26 | import { NgModule } from '@angular/core'; 27 | import { BrowserModule } from '@angular/platform-browser'; 28 | import { CountoModule } from 'angular2-counto'; 29 | 30 | @NgModule({ 31 | imports: [ BrowserModule, CountoModule ], 32 | declarations: [ AppComponent ], 33 | bootstrap: [ AppComponent ] 34 | }) 35 | export class AppModule { } 36 | ``` 37 | 38 | Example with currency pipe: 39 | ``` 40 |
{{counto | currency:'EUR':'symbol':'1.2-2'}}
41 | ``` 42 | 43 | ## Usage 44 | 45 | | Parameter | Required | Unit | Description | 46 | | ------------- | ------------- | ------------- | --------------------------------------- | 47 | | step | yes | milisecond | How fast counter is updated | 48 | | countTo | yes | number | Any start number | 49 | | countFrom | yes | number | Any end number | 50 | | duration | yes | seconds | Duration of animation | 51 | 52 | Any of above parameters can be freely binded to an event. Every time parameter changes, animation will be executed. 53 | You can use any pipe you want to modify output to your needs. 54 | 55 | ## Demo 56 | 57 | http://izupet.github.io/angular2-counto 58 | -------------------------------------------------------------------------------- /bs-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "baseDir": "example", 4 | "routes": { 5 | "/node_modules": "node_modules", 6 | "/src": "src" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { AppComponent } from './app.component'; 2 | 3 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 4 | import { By } from '@angular/platform-browser'; 5 | import { DebugElement } from '@angular/core'; 6 | 7 | describe('AppComponent', function () { 8 | let de: DebugElement; 9 | let comp: AppComponent; 10 | let fixture: ComponentFixture; 11 | 12 | beforeEach(async(() => { 13 | TestBed.configureTestingModule({ 14 | declarations: [ AppComponent ] 15 | }) 16 | .compileComponents(); 17 | })); 18 | 19 | beforeEach(() => { 20 | fixture = TestBed.createComponent(AppComponent); 21 | comp = fixture.componentInstance; 22 | de = fixture.debugElement.query(By.css('h1')); 23 | }); 24 | 25 | it('should create component', () => expect(comp).toBeDefined() ); 26 | 27 | it('should have expected

text', () => { 28 | fixture.detectChanges(); 29 | const h1 = de.nativeElement; 30 | expect(h1.innerText).toMatch(/angular/i, 31 | '

should say something about "Angular"'); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /example/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'my-app', 5 | template: `
{{intermediate | currency:'EUR':'symbol':'1.2-2'}}
`, 6 | }) 7 | export class AppComponent { 8 | 9 | onCountoEnd(): void { 10 | console.log('counto end'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { CountoModule } from 'angular2-counto'; 4 | import { AppComponent } from './app.component'; 5 | 6 | @NgModule({ 7 | imports: [ BrowserModule, CountoModule ], 8 | declarations: [ AppComponent ], 9 | bootstrap: [ AppComponent ] 10 | }) 11 | export class AppModule { } 12 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Counto Example 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | Loading... 19 | 20 | 21 | -------------------------------------------------------------------------------- /example/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app/app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /example/styles.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/izupet/angular2-counto/9b467b5774fe2a189fc646e60baf2cdfc91a65f2/example/styles.css -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "lib": [ "es2015", "dom" ], 10 | "noImplicitAny": true, 11 | "suppressImplicitAnyIndexErrors": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import { CountoDirective } from './src/counto.directive'; 2 | import { CountoModule } from './src/counto.module'; 3 | 4 | export { CountoDirective, CountoModule }; 5 | export default CountoModule; 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2-counto", 3 | "version": "1.2.5", 4 | "description": "Awesome angular package for counting animations.", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "scripts": { 10 | "build": "ngc", 11 | "build:example": "ngc -p example/", 12 | "lite": "lite-server", 13 | "serve": "concurrently \"npm run build\" \"npm run build:example\" \"npm run lite\" " 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/izupet/angular2-counto.git" 18 | }, 19 | "dependencies": {}, 20 | "keywords": [ 21 | "angular", 22 | "count", 23 | "animation", 24 | "awesome" 25 | ], 26 | "author": "Igor Zupet", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/izupet/angular2-counto/issues" 30 | }, 31 | "devDependencies": { 32 | "@angular/common": "^5.1.0", 33 | "@angular/compiler": "^5.1.0", 34 | "@angular/compiler-cli": "^5.1.0", 35 | "@angular/core": "^5.1.0", 36 | "@angular/forms": "^5.1.0", 37 | "@angular/http": "^5.1.0", 38 | "@angular/platform-browser": "^5.1.0", 39 | "@angular/platform-browser-dynamic": "^5.1.0", 40 | "@types/node": "~6.0.60", 41 | "concurrently": "^3.5.1", 42 | "core-js": "^2.4.1", 43 | "jasmine-core": "~2.8.0", 44 | "lite-server": "^2.3.0", 45 | "rxjs": "^5.5.6", 46 | "systemjs": "0.21.0", 47 | "typescript": "~2.5.3", 48 | "zone.js": "^0.8.19" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/counto.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, Input, Output, EventEmitter } from '@angular/core'; 2 | 3 | @Directive({ 4 | selector: '[counto]' 5 | }) 6 | 7 | export class CountoDirective { 8 | 9 | @Output() countoChange = new EventEmitter(); 10 | @Output() countoEnd = new EventEmitter(); 11 | private _timer: any; 12 | private _duration: number; 13 | private _countTo: number; 14 | private _countFrom: number; 15 | private _step: number; 16 | 17 | @Input() 18 | set duration(duration: string) { 19 | this._duration = parseFloat(duration); 20 | this.run(); 21 | } 22 | 23 | @Input() 24 | set countTo(countTo: string) { 25 | this._countTo = parseFloat(countTo); 26 | this.run(); 27 | } 28 | 29 | @Input() 30 | set countFrom(countFrom: string) { 31 | this._countFrom = parseFloat(countFrom); 32 | this.run(); 33 | } 34 | 35 | @Input() 36 | set step(step: string) { 37 | this._step = parseFloat(step); 38 | this.run(); 39 | } 40 | 41 | run() { 42 | var _this = this; 43 | clearInterval(_this._timer); 44 | 45 | if (isNaN(_this._duration)) { 46 | return false; 47 | } 48 | 49 | if (isNaN(_this._step)) { 50 | return false; 51 | } 52 | 53 | if (isNaN(_this._countFrom)) { 54 | return false; 55 | } 56 | 57 | if (isNaN(_this._countTo)) { 58 | return false; 59 | } 60 | 61 | if (_this._step <= 0) { 62 | console.info('Step must be greater than 0.'); 63 | return false; 64 | } 65 | 66 | if (_this._duration <= 0) { 67 | console.info('Duration must be greater than 0.'); 68 | return false; 69 | } 70 | 71 | if (_this._step > _this._duration*1000) { 72 | console.info('Step must be equal or smaller than duration.'); 73 | return false; 74 | } 75 | 76 | var intermediate = _this._countFrom; 77 | var increment = Math.abs(_this._countTo - _this._countFrom) / ((_this._duration * 1000) / _this._step); 78 | 79 | _this.countoChange.emit(intermediate); 80 | 81 | _this._timer = setInterval(function() { 82 | if (_this._countTo < _this._countFrom) { 83 | if (intermediate <= _this._countTo) { 84 | clearInterval(_this._timer); 85 | _this.countoChange.emit(_this._countTo); 86 | _this.countoEnd.emit(); 87 | } else { 88 | _this.countoChange.emit(intermediate); 89 | intermediate -= increment; 90 | } 91 | } else { 92 | if (intermediate >= _this._countTo) { 93 | clearInterval(_this._timer); 94 | _this.countoChange.emit(_this._countTo); 95 | _this.countoEnd.emit(); 96 | } else { 97 | _this.countoChange.emit(intermediate); 98 | intermediate += increment; 99 | } 100 | } 101 | }, _this._step); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/counto.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CountoDirective } from './counto.directive'; 3 | 4 | @NgModule({ 5 | declarations: [ CountoDirective ], 6 | exports: [ CountoDirective ] 7 | }) 8 | export class CountoModule {} 9 | -------------------------------------------------------------------------------- /tests/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/izupet/angular2-counto/9b467b5774fe2a189fc646e60baf2cdfc91a65f2/tests/.gitkeep -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "inlineSources": true, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "lib": [ "es2015", "dom" ], 11 | "noImplicitAny": true, 12 | "suppressImplicitAnyIndexErrors": true, 13 | "declaration": true 14 | }, 15 | "angularCompilerOptions": { 16 | "fullTemplateTypeCheck": true, 17 | "preserveWhiteSpaces": false, 18 | "strictMetadataEmit" : true 19 | }, 20 | "exclude": [ 21 | "node_modules", 22 | "example", 23 | "tests" 24 | ], 25 | "include": [ 26 | "index.ts", 27 | "src/*" 28 | ] 29 | } 30 | --------------------------------------------------------------------------------