diff options
Diffstat (limited to 'src/view/sequencer.ts')
-rw-r--r-- | src/view/sequencer.ts | 75 |
1 files changed, 55 insertions, 20 deletions
diff --git a/src/view/sequencer.ts b/src/view/sequencer.ts index 3bca278..74eb0ea 100644 --- a/src/view/sequencer.ts +++ b/src/view/sequencer.ts @@ -1,18 +1,33 @@ import h, { classNames } from 'lib/h' import * as soundsLib from 'sounds' +import { Sound } from 'sounds' import * as play from 'view/sequencer/play' import * as addRemoveBeat from 'view/sequencer/addRemoveBeat' import * as block from 'view/sequencer/block' export function view() { let index = -1 - let blocks = [true] + let blocks = [{ + [Sound.Bass]: true, + [Sound.Snare]: false, + [Sound.HitHatClosed]: false, + }] let blocksNode = h('div', { className: 'g-Sequencer__Blocks' }, - block.view({ - checked: true, - onCheck: checked => blocks[0] = checked - }) + block.column([ + { + checked: false, + onCheck: checked => blocks[0][Sound.HitHatClosed] = checked + }, + { + checked: false, + onCheck: checked => blocks[0][Sound.Snare] = checked + }, + { + checked: true, + onCheck: checked => blocks[0][Sound.Bass] = checked + } + ]) ) let onNextStep = (sounds: soundsLib.Sounds) => { @@ -24,9 +39,17 @@ export function view() { if (oldBlock !== undefined) oldBlock.classList.remove('g-Sequencer__Block--Beat') let newBlock = blocksNode.childNodes[newIndex] as HTMLElement + + // Trigger reflow between removing and adding the classname. + // Allow to re-trigger the animation if there is only one column. + // See https://css-tricks.com/restart-css-animation/ + void newBlock.offsetWidth + newBlock.classList.add('g-Sequencer__Block--Beat') - if (blocks[newIndex]) soundsLib.playKick(sounds) + soundsLib.all().forEach(sound => { + if (blocks[newIndex][sound]) soundsLib.play(sounds, sound) + }) } let sequencer = h('div', { className: 'g-Sequencer' }, @@ -46,25 +69,26 @@ export function view() { blocks.pop() }, onAdd: index => { - blocks.push(false) - blocksNode.appendChild(block.view({ - checked: false, - onCheck: checked => blocks[index] = checked - })) + blocks.push({ + [Sound.Bass]: false, + [Sound.Snare]: false, + [Sound.HitHatClosed]: false, + }) + blocksNode.appendChild(block.column( + soundsLib.all().map(sound => ({ + checked: false, + onCheck: checked => blocks[index][sound] = checked + })) + )) } }), h('div', { className: 'g-Sequencer__Grid' }, h('ol', - { className: 'g-Sequencer__Sounds' }, - h('li', - { onclick: async () => { - let sounds = await soundsLib.load() - soundsLib.playKick(sounds) - } - }, - 'Bass' - ) + { className: 'g-Sequencer__Column' }, + soundItem('Hit-hat (closed)', Sound.HitHatClosed), + soundItem('Snare', Sound.Snare), + soundItem('Bass', Sound.Bass) ), blocksNode ) @@ -72,3 +96,14 @@ export function view() { return sequencer } + +function soundItem(name: string, sound: Sound): Element { + return h('li', + { onclick: async () => { + let sounds = await soundsLib.load() + soundsLib.play(sounds, sound) + } + }, + name + ) +} |