JSFiddle - React, Tailwind, and code Playground

by Brett

HTML

<div class="audio-preview">
    <audio class="music" preload="auto">
        <source src="https://archive.org/download/testmp3testfile/mpthreetest.mp3">
    </audio>
    <div class="audioplayer">
        <button class="playbutton play"></button>
        <div class="timeline">
            <div class="playhead"></div>
        </div>
    </div>
</div>

SCSS

.audioplayer {
    width: 90%;
    height: 60px;
    margin: 0 auto;
    background: #fff;
    border-top: 1px solid #f4f4f4;
    .playbutton {
        float: left;
        height: 60px;
        width: 60px;
        border: none;
        opacity: .8;
        outline: none;
        cursor: pointer;
        &:hover {
            opacity: 1;
        }
    }
    .play {
        background: green url('https://www.alexkatz.me/codepen/images/play.png') no-repeat center center;
        background-size: 40% 40%;
    }
    .pause {
        background: red url('https://www.alexkatz.me/codepen/images/pause.png') no-repeat center center;
        background-size: 35% 35%;
    }
    .timeline {
        float: left;
        width: 80%;
        height: 20px;
        margin-top: 20px;
        padding-right: 20px;
        background: rgba(0, 0, 0, .3);
        border-radius: 15px;
        opacity: .9;
        cursor: pointer;
        &:hover {
            opacity: 1;
        }
        .playhead {
            width: 18px;
            height: 18px;
            margin-top: 1px;
			margin-left: 1px;
            background: #000;
            border-radius: 50%;
            //cursor: move;
            -webkit-transition: margin-left .1ms linear;
               -moz-transition: margin-left .1ms linear;
            		transition: margin-left .1ms linear;
        }
    }
}

JavaScript

// Audio player(s)
$('.audio-preview').each( function() {
	// set vars
    music = $(this).find('.music')[0]; // audio element
    player = $(this).find('.audioplayer'); // player
    button = $(this).find('.playbutton'); // play/pause button
	playhead = $(this).find('.playhead'); // playhead
	timeline = $(this).find('.timeline'); // timeline
	timelineWidth = timeline.width(); // timeline width - playhead width
	
	// is audio ready?
	function audioReady() {
  		return $.when.apply($, $(music).map( function() {
    		var ready = new $.Deferred();
    		$(this).one('canplay', ready.resolve);
    		return ready.promise();
  		}));
	}
	
	// when audio is ready...
	audioReady().then( function() {
		//alert('ready');
		duration = music.duration;
		
		$(button).on('click', function() {
			// if paused, start music
			if(music.paused) {
				music.play();
				button.removeClass('play').addClass('pause');
				
			} else { // if playing, pause music
				music.pause();
				button.removeClass('pause').addClass('play');
			}
		});
		
		$(music).bind('ended', function() {
			button.removeClass('pause').addClass('play');
			playhead.css('margin-left', '1px');
		});
		
		// timeUpdate event listener
		$(music).bind('timeupdate', timeUpdate);
		
		// Synchronizes playhead position with current point in audio
		function timeUpdate() {
			var percentPlayed = timelineWidth * (music.currentTime / duration);
			playhead.css('margin-left', percentPlayed + 'px');
		}
		
		// Makes timeline clickable
		$(timeline).on('click', function(event) {
			alert('click on timeline');
			moveplayhead(event);
			music.currentTime = duration * clickPercent(event);
		}, false);

		// returns click as decimal (.77) of the total timelineWidth
		function clickPercent(e) {
			return (e.pageX - timeline.offset().left) / timelineWidth;
		}

		// Makes playhead draggable
		$(playhead).on('mousedown', mouseDown, false);
		$(window).on('mouseup', mouseUp, false);

		// Boolean value so that mouse is moved on...