DevGang
Авторизоваться

Как воспроизводить аудио с помощью React

В этой статье я покажу вам, как я воспроизвожу аудио в интерфейсах React.

Настройка звука

Где-то на S3 у меня есть 4 аудиофайла, распространяемые CloudFront:

const musics = [
  'https://alterego.community/audio/classique.mp4',
  'https://alterego.community/audio/folk.mp4',
  'https://alterego.community/audio/electro.mp4',
  'https://alterego.community/audio/hip-hop.mp4'
];

Для каждой музыки я создаю аудиоэлемент и загружаю его при монтировании:

const [audio, setAudio] = useState<HTMLAudioElement>();

useEffect(() => {
  const _audio = new Audio(musics[props.num - 1]);
  _audio.load();
  _audio.addEventListener('canplaythrough', () => {
    setAudio(_audio);
  });
}, []);

Прослушивание взаимодействия пользователя

Я добавляю ref к родительскому элементу анимации Lottie, чтобы прослушивать события наведения и касания:

const musicRef = useRef<HTMLDivElement>(null);

<$Music ref={musicRef}>
  <Lottie hover loop={true} src={musicAnimation} />
</$Music>

Теперь, когда звук готов, я могу прослушивать взаимодействие пользователя:

useEffect(() => {
  if (!audio) return;
  if (!musicRef) return;

  const play = async () => {
    audio.play();
  };

  const stop = () => {
    audio.pause();
    audio.currentTime = 0;
  };

  const element = musicRef.current;

  if (element) {
    element.addEventListener('mouseenter', play);
    element.addEventListener('mouseleave', stop);
    element.addEventListener('touchstart', play);
    element.addEventListener('touchend', stop);

    return () => {
      element.removeEventListener('mouseenter', play);
      element.removeEventListener('mouseleave', stop);
      element.removeEventListener('touchstart', play);
      element.removeEventListener('touchend', stop);
    };
  }
}, [musicRef, audio]);

Подключаем состояние

Нам нужно сохранить выбранную музыку в состоянии:

export const PICK_MUSIC = '@@user/PICK_MUSIC';

type PickMusicPayload = {musicChoice: MusicChoice};

export type PickMusicAction = {
  type: '@@user/PICK_MUSIC';
  payload: PickMusicPayload;
};

const onPickMusic = {
  on: PICK_MUSIC,
  reduce: (state: State, payload: PickMusicPayload) => {
    const {musicChoice} = payload;
    state.preferredMusic = musicChoice;
  }
};

Затем часть React:

import {useTaverne} from 'taverne/hooks';

// ... in the component:

const {dispatch, pour} = useTaverne();
const preferredMusic = (pour('user.preferredMusic') || -1) as MusicChoice;

const pickMusic = (musicChoice: MusicChoice) => () => {
  dispatch({
    type: PICK_MUSIC,
    payload: {musicChoice}
  } as PickMusicAction);
};

<Music
  num={musicNum}
  selected={preferredMusic === musicNum}
  onClick={pickMusic(musicNum)}
/>

Монтируем все это вместе

Родительский компонент, отображающий всю музыку:

type MusicChoice = -1 | 1 | 2 | 3 | 4;
const musicChoices: Array<MusicChoice> = [1, 2, 3, 4];

<$Musics>
  {musicChoices.map(musicNum => (
    <Music
      key={`music-${musicNum}`}
      num={musicNum}
      selected={preferredMusic === musicNum}
      onClick={pickMusic(musicNum)}
    />
  ))}
</$Musics>

Источник:

#JavaScript #React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу