Аудио плеер
yarn add react-icons
Стили
.audioPlayer { --primary: #f40082; --secondary: #ffd200;
align-items: center; display: flex; width: 700px;}
.forwardBackward { background: none; border: none; display: flex; align-items: center; font-family: monospace; font-size: 16px; cursor: pointer;}
.forwardBackward:hover { color: var(--primary);}
.playPause { background: var(--primary); border: none; border-radius: 50%; width: 75px; height: 75px; font-size: 32px; color: var(--secondary); display: flex; justify-content: center; align-items:center;}
.play { position: relative; left: 5px;}
.currentTime,.duration { font-family: monospace; font-size: 16px;}
.currentTime { margin-left: 25px;}
.progressBar { --bar-bg: #ffe3d4; --seek-before-width: 0; --seek-before-color: #ffc2a1; --knobby: #3452a5; --selectedKnobby: #26c9c3;
appearance: none; background: var(--bar-bg);; border-radius: 10px; position: relative; width: 100%; height: 11px; outline: none;}
/* progress bar - safari */.progressBar::-webkit-slider-runnable-track { background: var(--bar-bg);; border-radius: 10px; position: relative; width: 100%; height: 11px; outline: none;}
/* progress bar - firefox */.progressBar::-moz-range-track { background: var(--bar-bg);; border-radius: 10px; position: relative; width: 100%; height: 11px; outline: none;}
.progressBar::-moz-focus-outer { border: 0;}
/* progress bar - chrome and safari */.progressBar::before { content: ''; height: 11px; width: var(--seek-before-width); background-color: var(--seek-before-color); border-top-left-radius: 10px; border-bottom-left-radius: 10px; position: absolute; top: 0; left: 0; z-index: 2; cursor: pointer;}
/* progress bar - firefox */.progressBar::-moz-range-progress { background-color: var(--seek-before-color); border-top-left-radius: 10px; border-bottom-left-radius: 10px; height: 11px;}
/* knobby - chrome and safari */.progressBar::-webkit-slider-thumb { -webkit-appearance: none; height: 15px; width: 15px; border-radius: 50%; border: none; background-color: var(--knobby); cursor: pointer; position: relative; margin: -2px 0 0 0; z-index: 3; box-sizing: border-box;}
/* knobby while dragging - chrome and safari */.progressBar:active::-webkit-slider-thumb { transform: scale(1.2); background: var(--selectedKnobby);}
/* knobby - firefox */.progressBar::-moz-range-thumb { height: 15px; width: 15px; border-radius: 50%; border: transparent; background-color: var(--knobby); cursor: pointer; position: relative; z-index: 3; box-sizing: border-box;}
/* knobby while dragging - firefox */.progressBar:active::-moz-range-thumb { transform: scale(1.2); background: var(--selectedKnobby);}
Компонент
'use client'
import React, { useState, useRef, useEffect } from 'react'import styles from "../../styles/AudioPlayer.module.css"; // Укажите путь к файлуimport { BsArrowLeftShort } from "react-icons/bs"import { BsArrowRightShort } from "react-icons/bs"import { FaPlay } from "react-icons/fa"import { FaPause } from "react-icons/fa"
const AudioPlayer = () => { // state const [isPlaying, setIsPlaying] = useState(false); const [duration, setDuration] = useState(0); const [currentTime, setCurrentTime] = useState(0);
// references const audioPlayer = useRef(); // reference our audio component const progressBar = useRef(); // reference our progress bar const animationRef = useRef(); // reference the animation
useEffect(() => { const seconds = Math.floor(audioPlayer.current.duration); setDuration(seconds); progressBar.current.max = seconds; }, [audioPlayer?.current?.loadedmetadata, audioPlayer?.current?.readyState]);
const calculateTime = (secs) => { const minutes = Math.floor(secs / 60); const returnedMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`; const seconds = Math.floor(secs % 60); const returnedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`; return `${returnedMinutes}:${returnedSeconds}`; }
const togglePlayPause = () => { const prevValue = isPlaying; setIsPlaying(!prevValue); if (!prevValue) { audioPlayer.current.play(); animationRef.current = requestAnimationFrame(whilePlaying) } else { audioPlayer.current.pause(); cancelAnimationFrame(animationRef.current); } }
const whilePlaying = () => { progressBar.current.value = audioPlayer.current.currentTime; changePlayerCurrentTime(); animationRef.current = requestAnimationFrame(whilePlaying); }
const changeRange = () => { audioPlayer.current.currentTime = progressBar.current.value; changePlayerCurrentTime(); }
const changePlayerCurrentTime = () => { progressBar.current.style.setProperty('--seek-before-width', `${progressBar.current.value / duration * 100}%`) setCurrentTime(progressBar.current.value); }
const backThirty = () => { progressBar.current.value = Number(progressBar.current.value - 30); changeRange(); }
const forwardThirty = () => { progressBar.current.value = Number(progressBar.current.value + 30); changeRange(); }
return ( <div className={styles.audioPlayer}> <audio ref={audioPlayer} src="https://listen.myrh.ru/id075696" preload="metadata"></audio> <button className={styles.forwardBackward} onClick={backThirty} title="Back"><BsArrowLeftShort /> 30</button> <button onClick={togglePlayPause} className={styles.playPause} title="Play/Pause"> {isPlaying ? <FaPause /> : <FaPlay className={styles.play} />} </button> <button className={styles.forwardBackward} onClick={forwardThirty} title="Next">30 <BsArrowRightShort /></button>
{/* current time */} <div className={styles.currentTime}>{calculateTime(currentTime)}</div>
{/* progress bar */} <div> <input type="range" className={styles.progressBar} defaultValue="0" ref={progressBar} onChange={changeRange} /> </div>
{/* duration */} <div className={styles.duration}>{(duration && !isNaN(duration)) && calculateTime(duration)}</div> </div> )}
export { AudioPlayer }
Плеер
import { AudioPlayer } from "../components/AudioPlayer" // Укажите путь к файлу
export default function Page() { return ( <div> <AudioPlayer /> </div> )}