Skip to content

Instantly share code, notes, and snippets.

@Janith-Umeda
Created October 10, 2023 16:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Janith-Umeda/c6046ac1e18ed025c857a1eb44b4c7cb to your computer and use it in GitHub Desktop.
Save Janith-Umeda/c6046ac1e18ed025c857a1eb44b4c7cb to your computer and use it in GitHub Desktop.
A Simple Audio Player with Modern UI using Tailwind, Material and React js.
import { FastForward, FastRewind, Pause, PlayArrow, Repeat, VolumeDown, VolumeOff, VolumeUp } from "@mui/icons-material";
import { useEffect, useRef, useState } from "react";
const AudioPlayer = ({src})=> {
const Player = useRef();
const [VolumeShow,setVolumeShow] = useState(false);
const [isMute,setMute] = useState(false);
const [volumeLevel,setVolumeLvl] = useState(50);
const [isPlay,setPlay] = useState(false);
const [isLoop,setLoop] = useState(false);
const [duration,setDuration] = useState('0:00');
const [current,setCurrent] = useState('0:00');
const [currentProg,setCurrProg] = useState(0);
useEffect(()=>{
if(isPlay){
Player.current.play();
}else{
Player.current.pause();
}
},[isPlay]);
const timeFormat = (currentTime)=>{
const minutes = Math.floor(currentTime / 60);
let seconds = Math.floor(currentTime % 60);
seconds = (seconds >= 10) ? seconds : "0" + seconds % 60;
const formatTime = minutes + ":" + seconds;
return formatTime;
};
useEffect(()=>{
if(isPlay){
setDuration(timeFormat(Player.current.duration));
Player.current.addEventListener("timeupdate",(e)=>{
setCurrent(timeFormat(Player.current?.currentTime));
setCurrProg(((Player.current?.currentTime/Player.current?.duration)*100).toFixed());
});
}
},[isPlay]);
useEffect(()=>{
const player = Player.current;
player?.addEventListener('play',()=>setPlay(true));
player?.addEventListener('pause',()=>setPlay(false));
return ()=>{
player.removeEventListener('play',()=>setPlay(true));
player.removeEventListener('pause',()=>setPlay(false));
}
});
useEffect(()=>{
Player.current.volume = Number(volumeLevel)/100;
},[volumeLevel]);
const RewindSeek = ()=>{
Player.current.currentTime = Player.current.currentTime - 10;
}
const ForwardSeek = ()=>{
Player.current.currentTime = Player.current.currentTime + 10;
}
return (
<div className="bg-slate-100 w-full rounded mb-3">
<div className="flex items-center justify-between w-full p-2 gap-3 h-16">
<div className="w-7">{current}</div>
<div className="bg-slate-400 w-full h-2 rounded relative overflow-clip">
<div className="absolute h-2 top-0 z-1 bg-red-400" style={{width:`${currentProg}%`}}></div>
</div>
<div className="w-7">{duration}</div>
</div>
<div className="bg-slate-300 h-16 flex items-center justify-around">
<div
className={`p-2 rounded-full ${isLoop?'bg-gray-400':''} hover:bg-gray-200 cursor-pointer`}
onClick={()=>setLoop((prev)=>!prev)}
>
<Repeat />
</div>
<div className="flex items-center gap-2">
<div
className="p-2 rounded-full hover:bg-gray-200 cursor-pointer active:bg-gray-100"
onClick={RewindSeek}
>
<FastRewind style={{fontSize:'28px'}}/>
</div>
<div
className="rounded-full bg-white w-14 h-14 flex items-center justify-center shadow-md hover:bg-green-300 cursor-pointer"
onClick={()=>setPlay((prev)=>!prev)}
>
{isPlay ? <Pause style={{fontSize:'40px'}}/> : <PlayArrow style={{fontSize:'40px'}}/>}
</div>
<div
className="p-2 rounded-full hover:bg-gray-200 cursor-pointer active:bg-gray-100"
onClick={ForwardSeek}
>
<FastForward style={{fontSize:'28px'}}/>
</div>
</div>
<div
className="p-2 rounded-full hover:bg-gray-200 cursor-pointer relative"
onMouseEnter={()=>setVolumeShow(true)}
// onMouseLeave={()=>setVolumeShow(false)}
>
<span>
{isMute || volumeLevel <= 0 ? <VolumeOff /> :( volumeLevel > 50 ? <VolumeUp /> : <VolumeDown />)}
</span>
<div
className={`${VolumeShow ? 'flex' : 'hidden'} flex-col items-center justify-center absolute w-[40px] h-[145px] bg-slate-400 top-[-150px] left-0 z-40 rounded-md shadow-md`}
// onMouseEnter={()=>setVolumeShow(true)}
onMouseLeave={()=>setVolumeShow(false)}
>
<input
type="range"
className="rotate-[270deg]"
min={0} max={100}
value={isMute ? 0 : volumeLevel}
onChange={(e)=>setVolumeLvl(e.target.value)}
onWheel={(e)=>{setVolumeLvl((prev)=>(e.deltaY < 0 ?(prev<100?prev+5:100):(prev>0?prev-5:0)))}}
/>
{/* <span className="absolute bottom-0"><VolumeOff style={{fontSize:'20px'}} /></span> */}
</div>
</div>
</div>
<audio className="hidden" src={src} ref={Player} muted={isMute} loop={isLoop} controls={true}></audio>
</div>
);
}
export default AudioPlayer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment