react-piano

repository·master·Indexed 43 days ago

https://github.com/kevinsqi/react-piano

A responsive, customizable React piano keyboard component (v3.1.3) that supports custom sounds, keyboard shortcuts, and configurable styling. It provides both a standard Piano component and a ControlledPiano component for external state management, utilizing MIDI numbers for note identification. The library handles the interactive UI and keyboard mapping, requiring developers to provide their own audio playback implementation via playNote and stopNote props.

Tokens
3.7K
Snippets
11
Records
17
Agent score
54%

What's inside react-piano

  1. Implement audio playback with playNote and stopNote

    master

    The react-piano component does not include built-in audio playback. You must provide your own audio implementation using the playNote and stopNote props. These props receive a midiNumber as an argument.

    For example, you can use libraries like soundfont-player to play realistic-sounding samples by triggering sounds within these callback functions.

  2. Record and playback notes

    master
    To implement a recording feature, use the onPlayNoteInput and onStopNoteInput props to capture MIDI numbers. You can then play back the recorded sequence by passing the array of captured MIDI numbers to the activeNotes prop.
  3. Basic usage of the Piano component

    master

    To use the piano, import the Piano component, KeyboardShortcuts utility, MidiNumbers utility, and the required CSS file.

    Note: Importing CSS requires a CSS loader (like in create-react-app). If you don't have one, manually copy src/styles.css from the package into your project.

    import { Piano, KeyboardShortcuts, MidiNumbers } from 'react-piano';
    import 'react-piano/dist/styles.css';
    
    function App() {
      const firstNote = MidiNumbers.fromNote('c3');
      const lastNote = MidiNumbers.fromNote('f5');
      const keyboardShortcuts = KeyboardShortcuts.create({
        firstNote: firstNote,
        lastNote: lastNote,
        keyboardConfig: KeyboardShortcuts.HOME_ROW,
      });
    
      return (
        <Piano
          noteRange={{ first: firstNote, last: lastNote }}
          playNote={(midiNumber) => {
            // Implement your audio playback logic here
          }}
          stopNote={(midiNumber) => {
            // Implement your audio playback logic here
          }}
          width={1000}
          keyboardShortcuts={keyboardShortcuts}
        />
      );
    }
  4. Customize Piano styles with CSS

    master

    You can override the default piano styles by importing your own CSS file after the react-piano/dist/styles.css import.

    Commonly used classes for overrides include:

    • .ReactPiano__Key--active: Styles for the currently active key.
    • .ReactPiano__Key--accidental: Styles for accidental keys.

    Example CSS:

    .ReactPiano__Key--active {
      background: #f00; /* Change active key to red */
    }
    
    .ReactPiano__Key--accidental {
      background: #000; /* Change accidental keys to black */
    }
    .ReactPiano__Key--active {
      background: #f00;  /* Change the default active key color to bright red */
    }
    
    .ReactPiano__Key--accidental {
      background: #000;  /* Change accidental keys to be completely black */
    }
  5. Develop the react-piano demo site locally

    master

    To develop the demo site locally and see changes from the react-piano package reflected in real-time, you must link the package to the demo repository.

    1. In the parent react-piano directory, install dependencies, link the package, and start the development server:

      yarn install
      yarn link
      yarn start
    2. In the react-piano-demo directory, install dependencies, link the local react-piano package, and start the demo server:

      yarn install
      yarn link react-piano
      yarn start

    The demo site will be available at http://localhost:3000.

    # In react-piano directory
    yarn install
    yarn link
    yarn start
    
    # In react-piano-demo directory
    yarn install
    yarn link react-piano
    yarn start
  6. Reference the Piano component props

    master

    The <Piano /> component accepts the following props:

    NameTypeDescription
    noteRangeRequired objectAn object with format { first: 48, last: 77 } where first and last are MIDI numbers. Use MidiNumbers.NATURAL_MIDI_NUMBERS to identify natural notes.
    playNoteRequired function(midiNumber) => void function to play a note specified by MIDI number.
    stopNoteRequired function(midiNumber) => void function to stop playing a note.
    widthConditionally required numberWidth in pixels. If omitted, the parent container must have an explicit width and height.
    activeNotesArray of numbersAn array of MIDI numbers (e.g., [44, 47, 54]) to programmatically play notes.
    keyWidthToHeightNumberRatio of key width to height.
    renderNoteLabelFunction({ keyboardShortcut, midiNumber, isActive, isAccidental }) => node function to render labels on keys with shortcuts.
    classNameStringA className to add to the component.
    disabledBooleanWhether to show the disabled state (useful during async audio loading).
    keyboardShortcutsArray of objectArray of { key: 'a', midiNumber: 48 } objects. Use KeyboardShortcuts.create to generate these. Do not generate this inline in JSX to avoid diffing issues.
    onPlayNoteInputFunction(midiNumber, { prevActiveNotes }) => void fires whenever a play-note event occurs.
    onStopNoteInputFunction(midiNumber, { prevActiveNotes }) => void fires whenever a stop-note event occurs.
  7. Import components from react-piano

    master

    The react-piano package exports several core components for building piano interfaces. You can import them directly from the package root.

    Available components:

    • Piano: An uncontrolled piano component.
    • ControlledPiano: A controlled piano component for managing state externally.
    • Keyboard: A component representing the piano keys.
    • KeyboardShortcuts: A component to handle keyboard input for playing notes.
    • MidiNumbers: A utility or component related to MIDI note number handling.
    import { Piano, ControlledPiano, Keyboard, KeyboardShortcuts, MidiNumbers } from 'react-piano';
  8. Handle note input events with onPlayNoteInput and onStopNoteInput

    master

    In addition to the required playNote and stopNote props (which are intended for audio playback), the Piano component provides onPlayNoteInput and onStopNoteInput callbacks. These are useful for synchronizing state or performing side effects when the user interacts with the keyboard.

    Both callbacks provide the midiNumber of the note being toggled and an object containing the prevActiveNotes (the state of active notes before the change).

    <Piano
      // ... other props
      onPlayNoteInput={(midiNumber, { prevActiveNotes }) => {
        console.log(`Note ${midiNumber} started. Previous notes:`, prevActiveNotes);
      }}
      onStopNoteInput={(midiNumber, { prevActiveNotes }) => {
        console.log(`Note ${midiNumber} stopped. Previous notes:`, prevActiveNotes);
      }}
    />
  9. Use the ControlledPiano component for external state management

    master

    The ControlledPiano component is used when you want to manage the piano's state (which notes are active) externally in your own application logic. Unlike an uncontrolled component, you must provide the activeNotes array and handle the audio playback logic yourself via the provided callback props.

    To use ControlledPiano, you must implement the following required props:

    • noteRange: An object defining the range of notes available.
    • activeNotes: An array of currently active MIDI numbers.
    • playNote: A function called by the component to trigger audio for a specific MIDI number.
    • stopNote: A function called by the component to stop audio for a specific MIDI number.
    • onPlayNoteInput: A function called when a note is triggered (e.g., via mouse, touch, or keyboard).
    • renderNoteLabel: A function that defines how note labels (like keyboard shortcuts) are rendered on the keys.
    <ControlledPiano
      noteRange={{ start: 60, end: 72 }}
      activeNotes={this.state.activeNotes}
      playNote={(midiNumber) => audioEngine.play(midiNumber)}
      stopNote={(midiNumber) => audioEngine.stop(midiNumber)}
      onPlayNoteInput={(midiNumber, prevActiveNotes) => this.handlePlay(midiNumber, prevActiveNotes)}
      onStopNoteInput={(midiNumber, prevActiveNotes) => this.handleStop(midiNumber, prevActiveNotes)}
      renderNoteLabel={({ keyboardShortcut, midiNumber, isActive, isAccidental }) => (
        <div>{keyboardShortcut}</div>
      )}
    />