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 { CONTROLS } from './enums'; |
||||
|
||||
function Controls(container, { animating, count, maxCount, speed }, customNodes) { |
||||
this.nodes = { |
||||
animating: createAnimatingControl(animating), |
||||
count: createCountControl(count, maxCount), |
||||
speed: createSpeedControl(speed), |
||||
} |
||||
|
||||
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 }); |
||||
export default function(destroy$, { |
||||
count = 1, |
||||
id, |
||||
maxCount = 10, |
||||
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); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
destroy$.subscribe((sourceId) => { |
||||
if (id !== sourceId) { |
||||
observables.animating$.next(false); |
||||
observables.count$.next(0); |
||||
} |
||||
}); |
||||
|
||||
return observables; |
||||
} |
||||
|
||||
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) { |
||||
this.nodes.speed.querySelector('span').innerHTML = |
||||
`Speed: ${value}`; |
||||
} |
||||
|
||||
if (key === CONTROLS.ANIMATING) { |
||||
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'); |
||||
label.className = 'controls-label'; |
||||
label.className = 'controls-animating'; |
||||
|
||||
const text = document.createElement('span'); |
||||
text.innerHTML = '...'; |
||||
|
||||
const checkbox = document.createElement('input'); |
||||
checkbox.type = 'checkbox'; |
||||
checkbox.checked = value; |
||||
checkbox.checked = false; |
||||
|
||||
label.appendChild(checkbox); |
||||
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'); |
||||
label.className = 'controls-range'; |
||||
|
||||
const text = document.createElement('span'); |
||||
text.innerHTML = '...'; |
||||
text.innerHTML = (initialValue == 1) ? '1 particle' : `${initialValue} particles`; |
||||
text.className = 'controls-range-text'; |
||||
|
||||
const slider = document.createElement('input'); |
||||
slider.type = 'range'; |
||||
slider.min = 1; |
||||
slider.max = max; |
||||
slider.value = value; |
||||
slider.value = initialValue; |
||||
slider.className = 'controls-range-input'; |
||||
|
||||
label.appendChild(text); |
||||
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'); |
||||
label.className = 'controls-range'; |
||||
|
||||
const text = document.createElement('span'); |
||||
text.className = 'controls-range-text'; |
||||
text.innerHTML = 'Speed: 0'; |
||||
|
||||
const slider = document.createElement('input'); |
||||
slider.type = 'range'; |
||||
slider.min = 1; |
||||
slider.max = 15; |
||||
slider.value = value; |
||||
slider.value = 4; |
||||
slider.className = 'controls-range-input'; |
||||
|
||||
label.appendChild(text); |
||||
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