Global animation management 1a 1b.

master
Ben Burlingham 8 years ago
parent ea7210309f
commit 21ba248754
  1. 83
      js/animation.js
  2. 2
      js/animation1b.js
  3. 10
      js/bundle.js
  4. 15
      js/controls.js
  5. 2
      js/index.js
  6. 107
      js/particle.js

@ -8,72 +8,27 @@ function Animation(observables, id) {
this.id = id;
this.observables = observables;
this.particles = [];
this.grid = new Grid();
this.fpsInterval = null;
this.container = document.createElement('div');
this.container.className = 'animationContainer';
document.getElementById(id).appendChild(this.container);
this.observables.animating$.subscribe(this.updateAnimating.bind(this));
this.observables.count$.skip(1).subscribe(this.updateCount.bind(this));
// observables.circle$, PROBABLY WON'T NEED THESE, WILL BE In PARTICLE
// observables.randomize$,
// observables.speed$
// this.observables.count$.next(99);
//<div class='animationContainer'></div>
// console.warn("Mounting Animation", this.id);
// console.warn('updateAnimating in Animation', isAnimating)
// this.isAnimating = isAnimating;
// if (isAnimating) {
// const fps$ = Rx.Observable.interval(1000 / 32)
// .takeWhile(_ => this.isAnimating);
//
// fps$.subscribe(this.nextFrame.bind(this));
// }
// this.container = container;
// this.particles = [];
// this.isAnimating = false;
// this.config = config;
// this.grid = new Grid();
// this.updateAnimating(false);
// this.updateCircle(config.circleControl);
// this.updateSpeed(config.speed);
// this.updateRandomize(this.config.randomizeControl);
// Must be last, after configs all set up and container is fully rendered.
// this.updateCount(this.config.count);
this.observables.count$.skip(1).subscribe(this.subscribeCount.bind(this));
this.observables.animating$.subscribe(this.subscribeAnimating.bind(this));
}
Animation.prototype.updateAnimating = function(isAnimating) {
Animation.prototype.subscribeAnimating = function(isAnimating) {
if (isAnimating === false) {
return;
clearInterval(this.fpsInterval);
} else {
const { fps$ } = this.observables;
this.fpsInterval = setInterval(fps$.next.bind(fps$), 1000 / 32);
}
const fps$ = Rx.Observable.interval(1000 / 32)
.takeUntil(this.observables.animating$);
fps$.subscribe(this.nextFrame.bind(this));
}
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.updateCount = function(count) {
Animation.prototype.subscribeCount = function(count) {
const bounds = this.container.getBoundingClientRect();
while (this.particles.length > count) {
@ -82,25 +37,9 @@ Animation.prototype.updateCount = function(count) {
}
while (this.particles.length < count) {
const p = new Particle(this.container, bounds, this.config, this.grid);
const p = new Particle(this.container, bounds, this.grid, this.observables);
this.particles.push(p);
}
}
Animation.prototype.updateSpeed = function(value) {
// Options must be stored; they are passed to new particles.
this.config.speed = value;
this.particles.forEach(p => p.updateConfig({ speed: value }));
}
Animation.prototype.updateCircle = function(value) {
this.config.showMovementCircle = value;
this.particles.forEach(p => p.updateConfig({ showMovementCircle: value }));
}
Animation.prototype.updateRandomize = function(value) {
this.config.randomize = value;
this.particles.forEach(p => p.updateConfig({ randomize: value }));
}
export default Animation;

@ -5,7 +5,7 @@ export default function(destroy$) {
const id = '1b';
const config = {
id,
max: 10
maxCount: 1000
};
const observables = Controls(destroy$, config);

File diff suppressed because one or more lines are too long

15
js/controls.js vendored

@ -14,6 +14,7 @@ export default function(destroy$, {
document.getElementById(id).appendChild(container);
const observables = {
fps$: new Rx.Subject(),
count$: createCountControl(container, 0, maxCount),
speed$: createSpeedControl(container),
circle$: showCircleControl ? createCircleControl(container) : undefined,
@ -156,8 +157,11 @@ function createCircleControl(container) {
container.appendChild(label);
const circle$ = Rx.Observable.fromEvent(label, 'change')
.map(evt => evt.target.checked);
const circle$ = new Rx.BehaviorSubject(true);
label.addEventListener('change', (evt) => {
circle$.next(evt.target.checked);
});
return circle$;
}
@ -180,8 +184,11 @@ function createRandomizeControl(container) {
container.appendChild(label);
const circle$ = Rx.Observable.fromEvent(label, 'change')
.map(evt => evt.target.checked);
const randomize$ = new Rx.BehaviorSubject(true);
label.addEventListener('change', (evt) => {
randomize$.next(evt.target.checked);
});
return randomize$;
}

@ -22,8 +22,8 @@ window.addEventListener('load', () => {
// TODO fix "hangup" small radius evade bug
// TODO don't load simulation until requested
// TODO sort out particle nextframe
// TODO subscriber on bounds change
// TODO abs positioning on controls elements so order doesn't matter
// TODO BehaviorSubject listener on bounds change
// TODO ANIM1ab free movement

@ -3,24 +3,20 @@ import { BEHAVIOR, ENTITIES, RAD } from './enums';
import Arc from './arc';
import Random from './random';
const baseConfig = {
behavior: BEHAVIOR.COHESION,
bounds: {},
color: 'red',
gridSize: 5,
randomize: true,
showArc: false,
showVision: false,
speed: 4,
visionRadius: 50
};
// ===== Constructor =====
function Particle(parent, bounds, config, globalGrid) {
this.config = Object.assign({}, baseConfig, config);
this.config.color = Random.color();
// this.config.bounds = bounds;
function Particle(parent, bounds, globalGrid, observables) {
this.config = {
behavior: BEHAVIOR.COHESION,
bounds,
color: Random.color(),
gridSize: 5,
randomize: true,
showArc: false,
showVision: false,
speed: 4,
visionRadius: 50
};
this.grids = {
global: globalGrid || {},
@ -43,10 +39,24 @@ function Particle(parent, bounds, config, globalGrid) {
this.isLeader = false;
this.arc = Arc.create(bounds, this.grids.global);
// this.updateConfig(this.config);
// this.grids.global.setPoint({ x: p.arc.endX, y: p.arc.endY, type: ENTITIES.PARTICLE }, p);
// this.nextFrame(globalGrid);
// this.grids.global.setPoint({ x: p.arc.endX, y: p.arc.endY, type: ENTITIES.PARTICLE }, p); // USE ID?
this.remove$ = new Rx.Subject();
observables.fps$
.takeUntil(this.remove$)
.subscribe(this.subscribeNextFrame.bind(this));
observables.speed$
.takeUntil(this.remove$)
.subscribe(this.subscribeSpeed.bind(this));
observables.circle$ && observables.circle$
.takeUntil(this.remove$)
.subscribe(this.subscribeCircle.bind(this));
// observables.randomize$.subscribe(this.subscribeRandomize.bind(this));
};
// ===== PROTOTYPE =====
@ -56,56 +66,50 @@ Particle.prototype.remove = function() {
const parent = this.nodes.container.parentNode;
parent.removeChild(this.nodes.container);
this.remove$.next();
delete this.nodes;
return this;
}
Particle.prototype.nextFrame = function() {
Particle.prototype.subscribeNextFrame = function() {
// this.arc = Arc.goto(this.arc, 200, 200, this.config.speed)
if (this.nodes === undefined) {
console.warn('no nodes in', this.id);
return;
}
this.arc = Arc.step(this.arc, this.config.bounds, this.config.speed);
if (this.leader !== null) {
this.arc = Arc.follow(this.arc, this.leader.arc);
// this.arc = Arc.follow(this.arc, this.leader.arc);
} else if (this.arc.length <= 0 && this.config.randomize) {
this.arc = Arc.randomize(this.arc);
}
// this.grids.vision = updateVisionGrid(this.arc, this.config, this.grids);
// const { hazards, particles } = look(this.arc, this.grids);
//
// if (hazards.length > 0) {
// this.arc = Arc.evade(this.arc);
// }
//
// this.updateLeader(particles);
// const prevX = p.arc.endX;
// const prevY = p.arc.endY;
// 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);
repaintContainer(this.nodes.container, this.arc);
repaintBody(this.nodes.body, this.arc, this.isLeader);
repaintCircle(this.nodes.circle, this.arc);
repaintVisionGrid(this.nodes.visionGrid, this.arc, this.grids);
}
Particle.prototype.subscriber = function({ key, value }) {
Particle.prototype.subscribeSpeed = function(value) {
this.config.speed = value;
}
Particle.prototype.updateConfig = function(config) {
// Object.assign(this.config, config);
//
// const { showArc, showVision } = this.config;
//
// if (showArc === true && this.nodes.circle === undefined) {
// this.nodes.circle = createCircleNode(this.config);
// this.nodes.container.appendChild(this.nodes.circle);
// }
//
// if (showArc === false && this.nodes.circle !== undefined) {
// this.nodes.container.removeChild(this.nodes.circle);
// delete this.nodes.circle;
// }
//
// if (showVision === true && this.nodes.visionGrid === undefined) {
// this.nodes.visionGrid = createVisionGridNodes(this.config, this.grids, this.nodes);
// }
@ -113,6 +117,19 @@ Particle.prototype.updateConfig = function(config) {
// if (showVision === false && this.nodes.visionGrid !== undefined) {
// delete this.nodex.visionGrid;
// }
Particle.prototype.subscribeCircle = function(show) {
if (show === false) {
this.nodes.container.removeChild(this.nodes.circle);
delete this.nodes.circle;
} else {
this.nodes.circle = createCircleNode(this.config);
this.nodes.container.appendChild(this.nodes.circle);
}
}
Particle.prototype.subscribeRandomize = function(value) {
this.config.randomize = value;
}
Particle.prototype.updateLeader = function(particles) {
@ -186,10 +203,6 @@ function createBodyNode(config) {
}
function createCircleNode(config) {
if (config.showArc === false) {
return undefined;
}
const node = document.createElement('div');
node.className = 'particle-movement-circle';
node.style.borderColor = config.color;

Loading…
Cancel
Save