How to make Music Player In ReactJs

How to make Music Player In ReactJs

How to make Music Player In ReactJs

How to make Music Player In ReactJs :-

Hello friend's in this post we know about how to create an reactjs music player web app.
this source code form codepen.

DEMO


Step 1 :) Add HTML

App.js file

function App() {
    return (
        <>
            <div id="root"></div>
            <a target="_blank" title="instagram/web__addict" href="https://www.instagram.com/web__addict/"><i class="fab fa-instagram"></i></a>
        </>
    );
}

export default App;



Step 2 :) Add CSS

style.css

@import url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css);
@import url(https://fonts.googleapis.com/css?family=Rubik:300,400,500,700&amp;display=swap);
@import url(https://cdnjs.cloudflare.com/ajax/libs/mediaelement/4.2.11/mediaelementplayer.min.css);

body {
    font-family"Rubik"sans-serif;
    color#071739;
    displayflex;
    justify-contentcenter;
    align-itemscenter;
    flex-directioncolumn;
    background#000;
  }
  body h1 {
    font-size36px;
    margin-bottom0;
  }
  body .card {
    displayflex;
    flex-directioncolumn;
    justify-contentcenter;
    align-itemscenter;
    max-width371px;
    padding20px 5px;
    margin-top40px;
    border-radius20px;
    color#fff;
    font-weight100;
    box-shadow0px 0px 70px 0px #274684;
    background#071739;
    overflowhidden;
  }
  body .card .current-song {
    displayflex;
    flex-directioncolumn;
    align-itemscenter;
    width100%;
    padding20px 0px;
    border-radius20px;
    color#071739;
    background#fff;
  }
  body .card .current-song audio {
    displaynone;
  }
  body .card .current-song .img-wrap {
    positionrelative;
    margin0 auto;
    width270px;
    height200px;
    overflowhidden;
    border-radius20px;
    box-shadow0px 10px 40px 0px rgba(39701320.7);
  }
  body .card .current-song .img-wrap img {
    width100%;
    height100%;
  }
  body .card .current-song .song-name {
    margin-top30px;
    font-size22px;
  }
  body .card .current-song .song-autor {
    color#709fdc;
  }
  body .card .current-song .time {
    displayflex;
    justify-contentspace-between;
    margin-top10px;
    width240px;
  }
  body .card .current-song #timeline {
    positionrelative;
    margin0 auto;
    width240px;
    height5px;
    background#709fdc;
    border-radius5px;
    cursorpointer;
  }
  body .card .current-song #timeline:hover .hover-playhead {
    opacity1;
  }
  body .card .current-song #timeline:hover .hover-playhead::before {
    opacity1;
  }
  body .card .current-song #timeline:hover .hover-playhead::after {
    opacity1;
  }
  body .card .current-song #timeline #playhead {
    positionrelative;
    z-index2;
    width0;
    height5px;
    border-radius5px;
    background#071739;
  }
  body .card .current-song #timeline .hover-playhead {
    positionabsolute;
    z-index1;
    top0;
    width0;
    height5px;
    opacity0;
    border-radius5px;
    background#274684;
    transition: opacity 0.3s;
  }
  body .card .current-song #timeline .hover-playhead::before {
    opacity0;
    contentattr(data-content);
    displayblock;
    positionabsolute;
    top-30px;
    right-23px;
    width40px;
    padding3px;
    text-aligncenter;
    colorwhite;
    background#274684;
    border-radiuscalc20px - 12px);
  }
  body .card .current-song #timeline .hover-playhead::after {
    opacity0;
    content"";
    displayblock;
    positionabsolute;
    top-8px;
    right-8px;
    border-top8px solid #274684;
    border-left8px solid transparent;
    border-right8px solid transparent;
  }
  body .card .current-song .controls {
    margin-top10px;
  }
  body .card .current-song .controls button.down-btn {
    color#071739;
    border-radius50%;
    margin15px;
    font-size18px;
    text-aligncenter;
    transition0.2s;
    cursorpointer;
    bordernone;
    background0;
  }
  body .card .current-song .controls button:focus {
    outlinenone;
  }
  body .card .current-song .controls button.play {
    width50px;
    height50px;
    border1px solid #e2e2e2;
  }
  body .card .current-song .controls button.play:hover {
    left0;
    box-shadow0px 0px 15px 0px rgba(39701320.7);
  }
  body .card .current-song .controls button.play .fa-play {
    transformtranslateX(2px);
  }
  body .card .current-song .controls button.prev-next,.down-btn {
    width35px;
    height35px;
  }
  body .card .current-song .controls button.prev-next:hover {
    transformscale(1.2);
  }
  body .card .play-list {
    displayflex;
    flex-directioncolumn;
    padding10px;
    height180px;
    overflow-yscroll;
  }
  body .card .play-list .track {
    displayflex;
    align-itemscenter;
    margin-bottom10px;
    border-radiuscalc20px - 10px);
    border1px solid transparent;
    transition0.3s;
    cursorpointer;
  }
  body .card .play-list .track:hover {
    background#274684;
    border-color#274684;
    positionrelative;
  }
  body .card .play-list .track.current-audio {
    background#274684;
    box-shadow0px 0px 15px 0px #274684;
  }
  body .card .play-list .track.play-now {
    background#274684;
    box-shadow0px 0px 15px 0px #274684;
    positionrelative;
  }
  body .card .play-list .track.play-now:after {
    content"";
    displayblock;
    positionabsolute;
    left17px;
    width57px;
    height57px;
    border-radiuscalc20px - 10px);
    font-size16px;
    -webkit-animation: play 2s linear infinite;
            animation: play 2s linear infinite;
    background-imageurl("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='iso-8859-1'%3F%3E%3C!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --%3E%3Csvg version='1.1' id='Capa_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 56 56' style='enable-background:new 0 0 56 56;' xml:space='preserve'%3E%3Cpath style='fill:%23071739;' d='M47.799,8.201c-10.935-10.935-28.663-10.935-39.598,0c-10.935,10.935-10.935,28.663,0,39.598 c10.935,10.935,28.663,10.935,39.598,0C58.734,36.864,58.734,19.136,47.799,8.201z M32.95,32.95c-2.734,2.734-7.166,2.734-9.899,0 c-2.734-2.734-2.734-7.166,0-9.899s7.166-2.734,9.899,0S35.683,30.216,32.95,32.95z'/%3E%3Cpath style='fill:%23E7ECED;' d='M35.778,20.222c-4.296-4.296-11.261-4.296-15.556,0c-4.296,4.296-4.296,11.261,0,15.556 c4.296,4.296,11.261,4.296,15.556,0C40.074,31.482,40.074,24.518,35.778,20.222z M30.121,30.121c-1.172,1.172-3.071,1.172-4.243,0 s-1.172-3.071,0-4.243s3.071-1.172,4.243,0S31.293,28.95,30.121,30.121z'/%3E%3Cg%3E%3Cpath style='fill:%23709fdc;' d='M35.778,35.778c-0.76,0.76-1.607,1.378-2.504,1.87l8.157,14.92c2.284-1.25,4.434-2.835,6.368-4.769 c1.934-1.934,3.519-4.084,4.769-6.368l-14.92-8.157C37.157,34.172,36.538,35.018,35.778,35.778z'/%3E%3Cpath style='fill:%23709fdc;' d='M20.222,20.222c0.76-0.76,1.607-1.378,2.504-1.87l-8.157-14.92c-2.284,1.25-4.434,2.835-6.368,4.769 s-3.519,4.084-4.769,6.368l14.92,8.157C18.843,21.828,19.462,20.982,20.222,20.222z'/%3E%3C/g%3E%3C/svg%3E");
  }
  body .card .play-list .track.play-now .track-img {
    filteropacity(70%);
  }
  body .card .play-list .track .track-img {
    width90px;
    border-radiuscalc20px - 10px);
  }
  body .card .play-list .track .track-discr {
    margin-left15px;
    displayflex;
    flex-directioncolumn;
    min-width190px;
  }
  body .card .play-list .track .track-discr .track-name {
    font-size17px;
    margin-top8px;
  }
  body .card .play-list .track .track-discr .track-author {
    margin-top8px;
    font-weight300;
    color#709fdc;
  }
  body .card .play-list .track .track-duration {
    min-width40px;
    margin-left10px;
    margin-right10px;
    font-weight500;
  }
  
  .fa-instagram {
    positionabsolute;
    color#071739;
    top3%;
    right2%;
    font-size38px;
  }
  
  .fa-instagram:hover {
    font-size42px;
    color#fff;
    transitionall 0.1s linear;
    cursorpointer;
  }
  
  .play-list::-webkit-scrollbar {
    width5px;
  }
  
  .play-list::-webkit-scrollbar-thumb {
    background#fff;
    border-radius5px;
  }
  
  .play-list::-webkit-scrollbar-track {
    background#071739;
  }
  
  @-webkit-keyframes play {
    0% {
      transformrotate(0deg);
    }
    100% {
      transformrotate(360deg);
    }
  }
  
  @keyframes play {
    0% {
      transformrotate(0deg);
    }
    100% {
      transformrotate(360deg);
    }
  }



Step 3 ) add File CardProfile.js


import './player.css'

class CardProfile extends React.Component {
  state = {
    index: 3,
    currentTime: '0:00',
    musicList: [{name:'Nice piano and ukulele'author: 'Royalty'img: 'https://www.bensound.com/bensound-img/buddy.jpg'audio:'https://www.bensound.com/bensound-music/bensound-buddy.mp3'duration: '2:02'}, 
      {name:'Gentle acoustic'author: 'Acoustic'img: 'https://www.bensound.com/bensound-img/sunny.jpg'audio:'https://www.bensound.com//bensound-music/bensound-sunny.mp3'duration: '2:20'},
      {name:'Corporate motivational'author: 'Corporate'img: 'https://www.bensound.com/bensound-img/energy.jpg'audio:'https://www.bensound.com/bensound-music/bensound-energy.mp3'duration: '2:59'},
      {name:'Slow cinematic'author: 'Royalty'img: 'https://www.bensound.com/bensound-img/slowmotion.jpg'audio:'https://www.bensound.com/bensound-music/bensound-slowmotion.mp3'duration: '3:26'}],
    pause: false,
  };


 componentDidMount() {
   this.playerRef.addEventListener("timeupdate"this.timeUpdatefalse);
   this.playerRef.addEventListener("ended"this.nextSongfalse);
   this.timelineRef.addEventListener("click"this.changeCurrentTimefalse);
   this.timelineRef.addEventListener("mousemove"this.hoverTimeLinefalse);
   this.timelineRef.addEventListener("mouseout"this.resetTimeLinefalse);
 }

  componentWillUnmount() {
    this.playerRef.removeEventListener("timeupdate"this.timeUpdate);
    this.playerRef.removeEventListener("ended"this.nextSong);
    this.timelineRef.removeEventListener("click"this.changeCurrentTime);
    this.timelineRef.removeEventListener("mousemove"this.hoverTimeLine);
    this.timelineRef.removeEventListener("mouseout"this.resetTimeLine);
  }

changeCurrentTime = (e=> {
  const duration = this.playerRef.duration;
  
  const playheadWidth = this.timelineRef.offsetWidth;
  const offsetWidht = this.timelineRef.offsetLeft;
  const userClickWidht = e.clientX - offsetWidht;
 
  const userClickWidhtInPercent = (userClickWidht*100)/playheadWidth;

  this.playheadRef.style.width = userClickWidhtInPercent + "%";
  this.playerRef.currentTime = (duration * userClickWidhtInPercent)/100;
}

hoverTimeLine = (e=> {
  const duration = this.playerRef.duration;
  
  const playheadWidth = this.timelineRef.offsetWidth
  
  const offsetWidht = this.timelineRef.offsetLeft;
  const userClickWidht = e.clientX - offsetWidht;
  const userClickWidhtInPercent = (userClickWidht*100)/playheadWidth;

  if(userClickWidhtInPercent <= 100){
    this.hoverPlayheadRef.style.width = userClickWidhtInPercent + "%";
  }
  
  const time = (duration * userClickWidhtInPercent)/100;
  
  if( (time >=0) && (time <= duration)){
    this.hoverPlayheadRef.dataset.content = this.formatTime(time);
  }
}

resetTimeLine = () => {
  this.hoverPlayheadRef.style.width = 0;
}

timeUpdate = () => {
  const duration = this.playerRef.duration;
  const timelineWidth = this.timelineRef.offsetWidth - this.playheadRef.offsetWidth;
  const playPercent = 100 * (this.playerRef.currentTime / duration);
    this.playheadRef.style.width = playPercent + "%";
  const currentTime = this.formatTime(parseInt(this.playerRef.currentTime));  
  this.setState({ 
    currentTime 
  });
}

formatTime = (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;
  }

  updatePlayer = () =>{
    const { musicListindex } = this.state;
    const currentSong = musicList[index];
    const audio = new Audio(currentSong.audio);
    this.playerRef.load();
  }
  
  nextSong = () => {
    const { musicListindexpause } = this.state;
  
    this.setState({ 
      index: (index + 1) % musicList.length
    });
    this.updatePlayer();
    if(pause){
      this.playerRef.play();
    }
  };

  prevSong = () => {
    const { musicListindexpause } = this.state;  
    
    this.setState({ 
      index: (index + musicList.length - 1) % musicList.length
    });
    this.updatePlayer();
    if(pause){
      this.playerRef.play();
    }
  };
   

  playOrPause = () =>{
    const { musicListindexpause } = this.state;
    const currentSong = musicList[index];
    const audio = new Audio(currentSong.audio);
    if( !this.state.pause ){
      this.playerRef.play();
    }else{
      this.playerRef.pause();
    }
    this.setState({
      pause: !pause
    })
  }
  
  clickAudio = (key=>{
    const { pause } = this.state;
    
    this.setState({
      index: key
    });
    
    this.updatePlayer();
    if(pause){
      this.playerRef.play();
    }
  }

  
  render() {
    const { musicListindexcurrentTimepause } = this.state;
    const currentSong = musicList[index];
    return (
      <div className="card">
        <div className="current-song">
          <audio ref={ref => this.playerRef = ref}>
            <source src={ currentSong.audio } type="audio/ogg"/>
              Your browser does not support the audio element.
          </audio>
          <div className="img-wrap">
            <img src={ currentSong.img }/>
           </div>
          <span className="song-name">{ currentSong.name }</span>
          <span className="song-autor">{ currentSong.author }</span>
          
          <div className="time">
            <div className="current-time">{ currentTime }</div>
            <div className="end-time">{ currentSong.duration }</div>
          </div>
          
          <div ref={ref => this.timelineRef = ref} id="timeline">
            <div ref={ref => this.playheadRef = ref} id="playhead"></div>
            <div ref={ref => this.hoverPlayheadRef = ref} class="hover-playhead" data-content="0:00"></div>
          </div>
          
          <div className="controls">
            <button onClick={this.prevSong} className="prev prev-next current-btn"><i className="fas fa-backward"></i></button>
            
            <button onClick={this.playOrPause} className="play current-btn">
              {
                (!pause) ? <i className="fas fa-play"></i>
                :<i class="fas fa-pause"></i>
              }
            </button>
            <button onClick={this.nextSong} className="next prev-next current-btn"><i className="fas fa-forward"></i></button>
          </div>
          
        </div>
        <div className="play-list" >
          {musicList.map( (musickey=0=>
                         <div key={key} 
                           onClick={()=>this.clickAudio(key)}
                           className={"track " + 
                             (index === key && !pause ?'current-audio':'') + 
                             (index === key && pause ?'play-now':'')} >
                           
                           <img className="track-img" src={music.img}/>
                           <div className="track-discr" >
                             <span className="track-name" >{music.name}</span>
                             <span className="track-author" >{music.author}</span>
                           </div>
                           <span className="track-duration" >
                             {(index === key)
                               ?currentTime
                               :music.duration
                             }
                           </span>
                         </div>
                        )}
        </div>
      </div>
    )
  }
}

ReactDOM.render(
  <CardProfile/>,
  document.getElementById('root')
)