Created
January 31, 2018 20:07
-
-
Save dfa1234/e30bf47482025fe14c058d27b0814ea6 to your computer and use it in GitHub Desktop.
HFO for frame animations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {AfterViewInit, Component, OnInit, QueryList, ViewChild, ViewChildren} from '@angular/core'; | |
import {Observable, Scheduler} from 'rxjs/Rx'; | |
/** | |
* | |
* From Scheduler source code: | |
* | |
* @property {Scheduler} queue Schedules on a queue in the current event frame | |
* (trampoline scheduler). Use this for iteration operations. | |
* @property {Scheduler} asap Schedules on the micro task queue, which uses the | |
* fastest transport mechanism available, either Node.js' `process.nextTick()` | |
* or Web Worker MessageChannel or setTimeout or others. Use this for | |
* asynchronous conversions. | |
* @property {Scheduler} async Schedules work with `setInterval`. Use this for | |
* time-based operations. | |
* @property {Scheduler} animationFrame Schedules work with `requestAnimationFrame`. | |
* Use this for synchronizing with the platform's painting | |
*/ | |
@Component({ | |
selector: 'app-root', | |
template: `<div class="my-div"> | |
<img #myImg src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> | |
<img #myImg src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> | |
<img #myImg src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> | |
</div>`, | |
styleUrls: ['./app.component.scss'] | |
}) | |
export class AppComponent implements OnInit,AfterViewInit{ | |
@ViewChildren("myImg") imgs: QueryList<any>; | |
myRange$ = Observable.range(0,Number.POSITIVE_INFINITY,Scheduler.animationFrame); | |
myInterval$ = Observable.interval(0,Scheduler.animationFrame); | |
msElapsed = ({scheduler = Scheduler.animationFrame, maxTimeInSecond = 5}) => Observable.defer(()=>{ | |
const starting = scheduler.now(); | |
return Observable.interval(0,scheduler) | |
.map(myInt => scheduler.now() - starting) | |
.takeWhile(() => scheduler.now() - starting < maxTimeInSecond*1000) | |
}); | |
distanceInPixel = v => ms => v * ms/1000; | |
fall = ({speed = 50,maxTimeInSecond=2}) => this.msElapsed({maxTimeInSecond}).map(this.distanceInPixel(speed)); | |
log = r => console.log(r); | |
duration = (ms = 5000,scheduler = Scheduler.animationFrame) => Observable.defer(()=>{ | |
const starting = scheduler.now(); | |
return Observable.interval(0,scheduler) | |
.map(myInt => { | |
let elapsed = scheduler.now() - starting; | |
return elapsed / ms | |
}) | |
.takeWhile(t => t <= 1) | |
}); | |
distance = distance => percent => percent * distance; | |
moveDown = myElem => duration$ => duration$ | |
.map(this.distance(500)) | |
.do( t => myElem.nativeElement.style.transform = `translateY(${t}px)`); | |
ngOnInit() {} | |
ngAfterViewInit() { | |
// AS velocity: | |
// fall({speed:50,maxTimeInSecond:5}).subscribe( | |
// r => this.myTranslation = `translateY(${r}px)`; | |
// ) | |
// AS duration (wary better): | |
//const moveImg = this.moveDown(this.myImg); | |
//First way to do it: | |
//moveDown(this.myImg)(duration(2000)).subscribe(r => console.log(r)) | |
//But better with "LET ME HAVE THE WHOLE OBSERVABLE" | |
//duration(2000) | |
// .let(this.moveDown(this.myImg)) | |
// .subscribe(log) | |
//same thing but with multiple references: | |
// console.log(this.imgs) | |
Observable.from(this.imgs.toArray()) | |
.concatMap((myImg,index)=>this.duration(400*(index+1)).let(this.moveDown(myImg))) | |
.subscribe() | |
//.subscribe(this.log) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment