Musical keyboard component written in React.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 3.8 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. # Musical Keyboard
  2. Musical keyboard component written in React.
  3. ## Installation
  4. This component is currently available in:
  5. * [Modal.sh JavaScript Package Registry](https://js.pack.modal.sh)
  6. * [npm](https://npmjs.com)
  7. * [GitHub Package Registry](https://npm.pkg.github.com)
  8. Once set up, install the package from the registry:
  9. ```shell script
  10. yarn add @theoryofnekomata/react-musical-keyboard
  11. ```
  12. ## Usage
  13. Basic usage is as follows, rendering the keyboard range of a modern grand piano (88 keys, from A0 to C8):
  14. ```jsx harmony
  15. import * as React from 'react'
  16. import ReactDOM from 'react-dom'
  17. import Keyboard from '@theoryofnekomata/react-musical-keyboard'
  18. const App = () => {
  19. return (
  20. <div>
  21. <Keyboard
  22. startKey={21}
  23. endKey={108}
  24. />
  25. </div>
  26. )
  27. }
  28. const container = window.document.createElement('div')
  29. window.document.body.appendChild(container)
  30. ReactDOM.render(<App />, container)
  31. ```
  32. ### Interactivity
  33. The library also supports keyboard maps for handling mouse, touch, and keyboard events:
  34. ```jsx harmony
  35. import * as React from 'react'
  36. import ReactDOM from 'react-dom'
  37. import Keyboard, { KeyboardMap } from '@theoryofnekomata/react-musical-keyboard'
  38. const App = () => {
  39. const handleKeysChange = keys => {
  40. // TODO handle key change: send MIDI events, play audio samples, etc.
  41. }
  42. return (
  43. <div>
  44. <Keyboard
  45. startKey={21}
  46. endKey={108}
  47. onChange={handleKeysChange}
  48. />
  49. </div>
  50. )
  51. }
  52. const container = window.document.createElement('div')
  53. window.document.body.appendChild(container)
  54. ReactDOM.render(<App />, container)
  55. ```
  56. It is capable of server-side rendering support, falling back to making the keys behave like links, checkboxes or radio buttons. Simply supply the `behavior` prop.
  57. ### Customization
  58. The component is stylable, just supply custom components for the keys:
  59. ```jsx harmony
  60. import * as React from 'react'
  61. import ReactDOM from 'react-dom'
  62. import Keyboard from '@theoryofnekomata/react-musical-keyboard'
  63. import NaturalKey from './my-styled-keys/NaturalKey'
  64. import AccidentalKey from './my-styled-keys/AccidentalKey'
  65. const App = () => {
  66. return (
  67. <div>
  68. <Keyboard
  69. startKey={21}
  70. endKey={108}
  71. keyComponents={{
  72. natural: NaturalKey,
  73. accidental: AccidentalKey
  74. }}
  75. />
  76. </div>
  77. )
  78. }
  79. const container = window.document.createElement('div')
  80. window.document.body.appendChild(container)
  81. ReactDOM.render(<App />, container)
  82. ```
  83. Components get their styles from CSS. The custom property `--opacity-highlight` is responsible for toggling the active, or "pressed" state of the key, simply assign it to the `opacity` style of the component you want to show for active keys.
  84. The library also exposes other custom properties: `--color-natural-key`, `--color-accidental-key`, and `--color-active-key` for basic coloring of the keys. You may expose your own properties for your custom key components.
  85. ```jsx harmony
  86. // ./my-styled-keys/NaturalKey.js
  87. import * as React from 'react'
  88. import NOT_PRESSED_KEY from './not-pressed.png'
  89. import PRESSED_KEY_OVERLAY from './pressed-overlay.png'
  90. const NaturalKey = ({
  91. keyChannels = []
  92. }) => {
  93. return (
  94. <div style={{ position: 'relative' }}>
  95. <img src={NOT_PRESSED_KEY} alt="" style={{ position: 'absolute', top: 0, left: 0, }} />
  96. <img src={PRESSED_KEY_OVERLAY} style={{ position: 'absolute', top: 0, left: 0, opacity: 'var(--opacity-highlight)', }} alt="" />
  97. </div>
  98. )
  99. }
  100. export default NaturalKey
  101. ```
  102. Take note that pressed keys from multiple channels might overlap, therefore it is advisable to support multiple channels pressing a single key at once.
  103. The component also supports orientation and mirroring, for instance, in use with horizontally-spanning piano rolls. Specify using the `orientation` and `mirroring` props.
  104. ## License
  105. MIT. See [License file](./LICENSE) for details.