parent
b861b78fba
commit
ea7210309f
11 changed files with 1089 additions and 1188 deletions
File diff suppressed because one or more lines are too long
@ -1,122 +1,187 @@ |
|||||||
import Rx, { Observable } from 'rxjs'; |
import Rx, { Observable } from 'rxjs'; |
||||||
import { CONTROLS } from './enums'; |
import { CONTROLS } from './enums'; |
||||||
|
|
||||||
function Controls(container, { animating, count, maxCount, speed }, customNodes) { |
export default function(destroy$, { |
||||||
this.nodes = { |
count = 1, |
||||||
animating: createAnimatingControl(animating), |
id, |
||||||
count: createCountControl(count, maxCount), |
maxCount = 10, |
||||||
speed: createSpeedControl(speed), |
showCircleControl = false, |
||||||
|
showRandomizeControl = false |
||||||
|
}) { |
||||||
|
const container = document.createElement('div'); |
||||||
|
container.className = 'controlsContainer'; |
||||||
|
container.id = `controls${id}`; |
||||||
|
document.getElementById(id).appendChild(container); |
||||||
|
|
||||||
|
const observables = { |
||||||
|
count$: createCountControl(container, 0, maxCount), |
||||||
|
speed$: createSpeedControl(container), |
||||||
|
circle$: showCircleControl ? createCircleControl(container) : undefined, |
||||||
|
randomize$: showRandomizeControl ? createRandomizeControl(container) : undefined, |
||||||
|
animating$: createAnimatingControl(container), |
||||||
|
}; |
||||||
|
|
||||||
|
observables.animating$.subscribe((isAnimating) => { |
||||||
|
if (isAnimating === true) { |
||||||
|
destroy$.next(id); |
||||||
|
|
||||||
|
if (observables.count$.getValue() === 0) { |
||||||
|
observables.count$.next(count); |
||||||
} |
} |
||||||
|
|
||||||
container.appendChild(this.nodes.count); |
|
||||||
container.appendChild(this.nodes.speed); |
|
||||||
|
|
||||||
if (customNodes !== undefined) { |
|
||||||
customNodes.forEach(node => { container.appendChild(node); }); |
|
||||||
} |
|
||||||
|
|
||||||
container.appendChild(this.nodes.animating); |
|
||||||
|
|
||||||
this.updateOptions({ key: CONTROLS.ANIMATING, value: animating }); |
|
||||||
this.updateOptions({ key: CONTROLS.COUNT, value: count }); |
|
||||||
this.updateOptions({ key: CONTROLS.SPEED, value: speed }); |
|
||||||
} |
|
||||||
|
|
||||||
Controls.prototype.updateOptions = function({ key, value}) { |
|
||||||
if (key === CONTROLS.COUNT) { |
|
||||||
this.nodes.count.querySelector('span').innerHTML = |
|
||||||
(value == 1) ? '1 particle' : `${value} particles`; |
|
||||||
} |
} |
||||||
|
}); |
||||||
|
|
||||||
if (key === CONTROLS.SPEED) { |
destroy$.subscribe((sourceId) => { |
||||||
this.nodes.speed.querySelector('span').innerHTML = |
if (id !== sourceId) { |
||||||
`Speed: ${value}`; |
observables.animating$.next(false); |
||||||
|
observables.count$.next(0); |
||||||
} |
} |
||||||
|
}); |
||||||
|
|
||||||
if (key === CONTROLS.ANIMATING) { |
return observables; |
||||||
this.nodes.animating.querySelector('span').innerHTML = |
|
||||||
(value ? '◼ Stop' : '▶ Start'); |
|
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
Controls.prototype.mount = function(customNodes) { |
|
||||||
const animating$ = Rx.Observable.fromEvent(this.nodes.animating, 'change') |
|
||||||
.map(evt => ({ key: CONTROLS.ANIMATING, value: evt.target.checked })); |
|
||||||
|
|
||||||
const count$ = Rx.Observable.fromEvent(this.nodes.count, 'input') |
|
||||||
.map(evt => ({ key: CONTROLS.COUNT, value: evt.target.value * 1 })); |
|
||||||
|
|
||||||
const speed$ = Rx.Observable.fromEvent(this.nodes.speed, 'input') |
|
||||||
.map(evt => ({ key: CONTROLS.SPEED, value: evt.target.value * 1 })); |
|
||||||
|
|
||||||
const eventStack$ = Rx.Observable.merge( |
|
||||||
animating$, |
|
||||||
count$, |
|
||||||
speed$ |
|
||||||
); |
|
||||||
|
|
||||||
eventStack$.subscribe(this.updateOptions.bind(this)); |
|
||||||
|
|
||||||
return eventStack$; |
|
||||||
} |
|
||||||
|
|
||||||
function createAnimatingControl(value) { |
function createAnimatingControl(container) { |
||||||
const label = document.createElement('label'); |
const label = document.createElement('label'); |
||||||
label.className = 'controls-label'; |
label.className = 'controls-label'; |
||||||
label.className = 'controls-animating'; |
label.className = 'controls-animating'; |
||||||
|
|
||||||
const text = document.createElement('span'); |
const text = document.createElement('span'); |
||||||
text.innerHTML = '...'; |
|
||||||
|
|
||||||
const checkbox = document.createElement('input'); |
const checkbox = document.createElement('input'); |
||||||
checkbox.type = 'checkbox'; |
checkbox.type = 'checkbox'; |
||||||
checkbox.checked = value; |
checkbox.checked = false; |
||||||
|
|
||||||
label.appendChild(checkbox); |
label.appendChild(checkbox); |
||||||
label.appendChild(text); |
label.appendChild(text); |
||||||
|
|
||||||
return label; |
container.appendChild(label); |
||||||
|
|
||||||
|
const animating$ = new Rx.BehaviorSubject(false); |
||||||
|
|
||||||
|
label.addEventListener('change', (evt) => { |
||||||
|
animating$.next(evt.target.checked); |
||||||
|
}); |
||||||
|
|
||||||
|
animating$.subscribe((isAnimating) => { |
||||||
|
text.innerHTML = (isAnimating ? '◼ Stop' : '▶ Start'); |
||||||
|
checkbox.checked = isAnimating; |
||||||
|
}); |
||||||
|
|
||||||
|
return animating$; |
||||||
} |
} |
||||||
|
|
||||||
function createCountControl(value, max) { |
function createCountControl(container, initialValue, max) { |
||||||
const label = document.createElement('label'); |
const label = document.createElement('label'); |
||||||
label.className = 'controls-range'; |
label.className = 'controls-range'; |
||||||
|
|
||||||
const text = document.createElement('span'); |
const text = document.createElement('span'); |
||||||
text.innerHTML = '...'; |
text.innerHTML = (initialValue == 1) ? '1 particle' : `${initialValue} particles`; |
||||||
text.className = 'controls-range-text'; |
text.className = 'controls-range-text'; |
||||||
|
|
||||||
const slider = document.createElement('input'); |
const slider = document.createElement('input'); |
||||||
slider.type = 'range'; |
slider.type = 'range'; |
||||||
slider.min = 1; |
slider.min = 1; |
||||||
slider.max = max; |
slider.max = max; |
||||||
slider.value = value; |
slider.value = initialValue; |
||||||
slider.className = 'controls-range-input'; |
slider.className = 'controls-range-input'; |
||||||
|
|
||||||
label.appendChild(text); |
label.appendChild(text); |
||||||
label.appendChild(slider); |
label.appendChild(slider); |
||||||
|
|
||||||
return label; |
container.appendChild(label); |
||||||
|
|
||||||
|
const count$ = new Rx.BehaviorSubject(initialValue); |
||||||
|
|
||||||
|
label.addEventListener('input', (evt) => { |
||||||
|
count$.next(evt.target.value * 1); |
||||||
|
}); |
||||||
|
|
||||||
|
count$.subscribe((value) => { |
||||||
|
text.innerHTML = (value == 1) ? '1 particle' : `${value} particles`; |
||||||
|
}); |
||||||
|
|
||||||
|
return count$; |
||||||
} |
} |
||||||
|
|
||||||
function createSpeedControl(value) { |
function createSpeedControl(container) { |
||||||
const label = document.createElement('label'); |
const label = document.createElement('label'); |
||||||
label.className = 'controls-range'; |
label.className = 'controls-range'; |
||||||
|
|
||||||
const text = document.createElement('span'); |
const text = document.createElement('span'); |
||||||
text.className = 'controls-range-text'; |
text.className = 'controls-range-text'; |
||||||
|
text.innerHTML = 'Speed: 0'; |
||||||
|
|
||||||
const slider = document.createElement('input'); |
const slider = document.createElement('input'); |
||||||
slider.type = 'range'; |
slider.type = 'range'; |
||||||
slider.min = 1; |
slider.min = 1; |
||||||
slider.max = 15; |
slider.max = 15; |
||||||
slider.value = value; |
slider.value = 4; |
||||||
slider.className = 'controls-range-input'; |
slider.className = 'controls-range-input'; |
||||||
|
|
||||||
label.appendChild(text); |
label.appendChild(text); |
||||||
label.appendChild(slider); |
label.appendChild(slider); |
||||||
|
|
||||||
return label; |
container.appendChild(label); |
||||||
|
|
||||||
|
const speed$ = new Rx.BehaviorSubject(slider.value); |
||||||
|
|
||||||
|
label.addEventListener('input', (evt) => { |
||||||
|
speed$.next(evt.target.value * 1); |
||||||
|
}); |
||||||
|
|
||||||
|
speed$.subscribe((value) => { |
||||||
|
text.innerHTML = `Speed: ${value}`; |
||||||
|
}); |
||||||
|
|
||||||
|
return speed$; |
||||||
} |
} |
||||||
|
|
||||||
export default Controls; |
function createCircleControl(container) { |
||||||
|
const label = document.createElement('label'); |
||||||
|
label.className = 'controls-checkbox'; |
||||||
|
|
||||||
|
const text = document.createElement('span'); |
||||||
|
text.innerHTML = 'Show movement circle'; |
||||||
|
text.className = 'controls-checkbox-text'; |
||||||
|
|
||||||
|
const checkbox = document.createElement('input'); |
||||||
|
checkbox.type = 'checkbox'; |
||||||
|
checkbox.className = 'controls-checkbox-input'; |
||||||
|
checkbox.checked = true; |
||||||
|
|
||||||
|
label.appendChild(checkbox); |
||||||
|
label.appendChild(text); |
||||||
|
|
||||||
|
container.appendChild(label); |
||||||
|
|
||||||
|
const circle$ = Rx.Observable.fromEvent(label, 'change') |
||||||
|
.map(evt => evt.target.checked); |
||||||
|
|
||||||
|
return circle$; |
||||||
|
} |
||||||
|
|
||||||
|
function createRandomizeControl(container) { |
||||||
|
const label = document.createElement('label'); |
||||||
|
label.className = 'controls-checkbox'; |
||||||
|
|
||||||
|
const text = document.createElement('span'); |
||||||
|
text.innerHTML = 'Randomize movement'; |
||||||
|
text.className = 'controls-checkbox-text'; |
||||||
|
|
||||||
|
const checkbox = document.createElement('input'); |
||||||
|
checkbox.type = 'checkbox'; |
||||||
|
checkbox.className = 'controls-checkbox-input'; |
||||||
|
checkbox.checked = true; |
||||||
|
|
||||||
|
label.appendChild(checkbox); |
||||||
|
label.appendChild(text); |
||||||
|
|
||||||
|
container.appendChild(label); |
||||||
|
|
||||||
|
const circle$ = Rx.Observable.fromEvent(label, 'change') |
||||||
|
.map(evt => evt.target.checked); |
||||||
|
|
||||||
|
return randomize$; |
||||||
|
} |
||||||
|
Loading…
Reference in new issue