JSFiddle - React, Tailwind, and code Playground
by dumptyd
HTML
<link rel="stylesheet" href="https://bootswatch.com/cosmo/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<audio src="http://api.soundcloud.com/tracks/329825886/stream?client_id=f8dc78d527a14157cce82626661b9607&.mp3" id="audio-el"></audio>
<div class="container text-center">
<div class="player text-left">
<div class="screen"></div>
<div class="controls">
<div class="control pause-play valign halign pull-left">
<div id="play">
<i class="fa fa-play"></i>
</div>
</div>
<div class="control i-progress valign ">
<div class="progress">
<div class="progress-bar"></div>
</div>
</div>
</div>
</div>
</div>
CSS
.player {
display: inline-block;
box-sizing: border-box;
width: 80%;
min-width: 400px;
max-width: 700px;
height: 300px;
margin-top: 50px;
border: 2px solid #999;
position: relative;
}
.player > .screen {
height: 90%;
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 50%;
background-color: #555;
}
.player > .controls {
height: 10%;
border-top: 2px solid #999;
padding: 0 10px;
width: 100%;
position: relative;
}
.controls > .control {
cursor: pointer;
height: 100%;
}
.pause-play {
width: 10%
}
.i-progress {
width: 90%;
}
.i-progress > .progress {
margin-bottom: 0;
width: 100%;
}
.i-progress > .progress > .progress-bar {
transition: width 50ms linear;
}
.valign {
display: flex;
align-items: center;
}
.halign {
justify-content: center;
}
JavaScript
$(document).ready(function() {
const images = new Array(10).fill(0).map((_, i) => `https://dummyimage.com/600x400/000/fff.png&text=Slide ${i + 1}`);
const audioEl = document.querySelector('#audio-el'),
duration = audioEl.duration;
let last = 0;
const dataArr = images.map((img, idx) => {
const obj = {
timestamp: {
start: last,
end: (duration / images.length) + last
},
img
};
last = obj.timestamp.end;
return obj;
});
const state = {
playing: false,
currentSlideIdx: 0,
playingSlideIdx: -1
};
const utils = {
setSlide(idx) {
if(idx === state.playingSlideIdx) return;
$('.screen').css('background-image', `url('${dataArr[idx].img}')`);
state.playingSlideIdx = state.currentSlideIdx;
},
timeUpdated() {
const ct = audioEl.currentTime;
for (let i = 0; i < dataArr.length; ++i) {
const ts = dataArr[i].timestamp;
if (ts.end >= ct && ts.start <= ct) {
state.currentSlideIdx = i;
utils.setSlide(i);
break;
}
}
}
};
audioEl.volume = 0.1;
audioEl.playbackRate = 1;
const intervalHandler = function() {
const ct = audioEl.currentTime;
const width = (ct / duration) * 100;
$('.i-progress > .progress > .progress-bar').css('width', `${width}%`);
if (ct > dataArr[state.currentSlideIdx].timestamp.end) state.currentSlideIdx++;
if (state.currentSlideIdx !== state.playingSlideIdx) {
utils.setSlide(state.currentSlideIdx);
}
};
let intervalID = setInterval(intervalHandler, 50);
$('#play').click(function() {
if (state.playing) {
$('#play').html('<i class="fa fa-play">');
audioEl.pause();
} else {
$('#play').html('<i class="fa fa-pause">');
audioEl.play();
}
state.playing = !state.playing;
});
audioEl.onended = function() {
$('#play').html('<i class="fa fa-play">');
state.playing = false;
};
$('.i-progress >...