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. 93
      js/particle.js

@ -8,72 +8,27 @@ function Animation(observables, id) {
this.id = id; this.id = id;
this.observables = observables; this.observables = observables;
this.particles = []; this.particles = [];
this.grid = new Grid();
this.fpsInterval = null;
this.container = document.createElement('div'); this.container = document.createElement('div');
this.container.className = 'animationContainer'; this.container.className = 'animationContainer';
document.getElementById(id).appendChild(this.container); document.getElementById(id).appendChild(this.container);
this.observables.animating$.subscribe(this.updateAnimating.bind(this)); this.observables.count$.skip(1).subscribe(this.subscribeCount.bind(this));
this.observables.count$.skip(1).subscribe(this.updateCount.bind(this)); this.observables.animating$.subscribe(this.subscribeAnimating.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);
} }
Animation.prototype.updateAnimating = function(isAnimating) { Animation.prototype.subscribeAnimating = function(isAnimating) {
if (isAnimating === false) { if (isAnimating === false) {
return; clearInterval(this.fpsInterval);
} } else {
const { fps$ } = this.observables;
const fps$ = Rx.Observable.interval(1000 / 32) this.fpsInterval = setInterval(fps$.next.bind(fps$), 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(); const bounds = this.container.getBoundingClientRect();
while (this.particles.length > count) { while (this.particles.length > count) {
@ -82,25 +37,9 @@ Animation.prototype.updateCount = function(count) {
} }
while (this.particles.length < 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); 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; export default Animation;

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

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

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

Loading…
Cancel
Save