import Rx, { Observable } from 'rxjs'; import Grid from './grid'; import Particle from './particle'; import Controls from './controls'; import { CONTROLS, ENTITIES } from './enums'; function Animation() { // TODO remove bottom padding from Disqus // TODO fix "hangup" small radius evade bug // TODO don't load simulation until requested // TODO sort out particle nextframe // TODO ANIM1ab free movement // TODO ANIM3a streamline updateLeader // TODO ANIM3b separation // TODO ANIM3c alignment }; Animation.prototype.destroy = function() { } Animation.prototype.subscriber = function({ key, value }) { switch(key) { case CONTROLS.ANIMATING: this.updateAnimating(value); break; case CONTROLS.COUNT: this.updateCount(value); break; case CONTROLS.SPEED: this.updateSpeed(value); break; } } Animation.prototype.nextFrame = function() { this.particles.forEach(p => { const prevX = p.arc.endX; const prevY = p.arc.endY; p.nextFrame(); this.grid.deletePoint({ x: prevX, y: prevY, type: ENTITIES.PARTICLE }); this.grid.setPoint({ x: p.arc.endX, y: p.arc.endY, type: ENTITIES.PARTICLE }, p); }); } Animation.prototype.updateAnimating = function(isAnimating) { this.options.animating = isAnimating; if (isAnimating) { const fps$ = Rx.Observable.interval(1000 / 32) .takeWhile(_ => this.options.animating); fps$.subscribe(this.nextFrame.bind(this)); } } Animation.prototype.updateCount = function(count) { const bounds = this.container.getBoundingClientRect(); while (this.particles.length > count) { const p = this.particles.pop(); this.grid.deletePoint({ x: p.arc.endX, y: p.arc.endY, type: ENTITIES.PARTICLE }); p.remove(); } while (this.particles.length < count) { const p = new Particle(this.container, bounds, this.options, this.grid); this.grid.setPoint({ x: p.arc.endX, y: p.arc.endY, type: ENTITIES.PARTICLE }, p); this.particles.push(p); } } Animation.prototype.updateSpeed = function(value) { this.options.speed = value; this.particles.forEach(p => p.updateConfig({ speed: value })); } export default Animation;