Musical keyboard component written in React.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.tsx 2.6 KiB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import * as React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import Keyboard, { KeyboardMap } from '../src'
  4. import * as Channel from './controllers/Channel'
  5. import * as Instrument from './controllers/Instrument'
  6. import * as Generator from './controllers/Generator'
  7. import keyboardMapping from './services/keyboardMapping'
  8. import SoundGenerator from './services/SoundGenerator'
  9. const App = () => {
  10. const [channel, setChannel] = React.useState(0)
  11. const [keyChannels, setKeyChannels] = React.useState<{ key: number; velocity: number; channel: number }[]>([])
  12. const [instruments, setInstruments, ] = React.useState<string[]>([])
  13. const [instrument, setInstrument] = React.useState(0)
  14. const generator = React.useRef<SoundGenerator | undefined>(undefined)
  15. const scrollRef = React.useRef<HTMLDivElement>(null)
  16. React.useEffect(() => {
  17. if (!generator.current) {
  18. return
  19. }
  20. Instrument.reflect({ generator: generator.current, channel, instrument })
  21. }, [channel, instrument])
  22. React.useEffect(() => {
  23. Generator
  24. .load()
  25. .then(g => {
  26. Instrument.initialize({ setInstruments, generator: generator.current = g, })
  27. })
  28. }, [])
  29. React.useEffect(() => {
  30. const { current } = scrollRef
  31. if (current) {
  32. current.scrollLeft = current.scrollWidth * 0.4668
  33. }
  34. }, [scrollRef])
  35. return (
  36. <React.Fragment>
  37. <input
  38. type="number"
  39. id="channel"
  40. min={0}
  41. max={15}
  42. onChange={Channel.change({ setChannel, })}
  43. defaultValue={0}
  44. />
  45. <select
  46. id="instrument"
  47. onChange={Instrument.change({ setInstrument, })}
  48. defaultValue={0}
  49. >
  50. {Array.isArray(instruments) && instruments.map((name, i) => (
  51. <option
  52. key={i}
  53. value={i}
  54. >
  55. {name}
  56. </option>
  57. ))}
  58. </select>
  59. <div
  60. id="keyboard"
  61. ref={scrollRef}
  62. >
  63. <div
  64. id="keyboard-scroll"
  65. >
  66. <Keyboard
  67. hasMap
  68. startKey={0}
  69. endKey={127}
  70. keyChannels={keyChannels}
  71. height="100%"
  72. >
  73. <KeyboardMap
  74. channel={channel}
  75. onChange={Channel.handle({ setKeyChannels, generator: generator.current!, })}
  76. keyboardMapping={keyboardMapping}
  77. />
  78. </Keyboard>
  79. </div>
  80. </div>
  81. </React.Fragment>
  82. )
  83. }
  84. const container = window.document.createElement('div')
  85. container.style.display = 'contents'
  86. window.document.body.appendChild(container)
  87. ReactDOM.render(<App />, container)