Skip to content

Instantly share code, notes, and snippets.

@Janith-Umeda
Created October 10, 2023 16:54
Show Gist options
  • Select an option

  • Save Janith-Umeda/c6046ac1e18ed025c857a1eb44b4c7cb to your computer and use it in GitHub Desktop.

Select an option

Save Janith-Umeda/c6046ac1e18ed025c857a1eb44b4c7cb to your computer and use it in GitHub Desktop.

Revisions

  1. Janith-Umeda created this gist Oct 10, 2023.
    133 changes: 133 additions & 0 deletions AudioPlayer.jsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,133 @@

    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;