Skip to content

Instantly share code, notes, and snippets.

@dfa1234
Created January 31, 2018 20:07
Show Gist options
  • Save dfa1234/e30bf47482025fe14c058d27b0814ea6 to your computer and use it in GitHub Desktop.
Save dfa1234/e30bf47482025fe14c058d27b0814ea6 to your computer and use it in GitHub Desktop.
HFO for frame animations
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