Skip to content

Instantly share code, notes, and snippets.

@DyllanJsLua
Created October 8, 2020 17:38
Show Gist options
  • Save DyllanJsLua/3cd7f82d2aef34520ad030ca071e285f to your computer and use it in GitHub Desktop.
Save DyllanJsLua/3cd7f82d2aef34520ad030ca071e285f to your computer and use it in GitHub Desktop.
Web Audio Visualizer
<audio id="audio"></audio>
<canvas id="canvas"></canvas>
<div class="container">
<div class="previous">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24"><polyline fill="none" stroke="#95a5a6" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" points="14,16 10,12 14,8 &#10;&#9;" transform="translate(0, 0)" stroke-linejoin="round"/></svg>
</div>
<div class="text-container">
<div class="text"> Todays pick: Do or Die</div>
<div class="text">Todays pick: Drop the Game</div>
<div class="text">Todays pick: Retrograde</div>
<div class="text"> Todays pick: Lost in the Moment</div>
<div class="text">Todays pick: Stay with Me</div>
<div class="text">Todays pick: Mad World</div>
</div>
<div class="next">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24"><polyline fill="none" stroke="#95a5a6" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" points="10,8 14,12 10,16 &#10;&#9;" transform="translate(0, 0)" stroke-linejoin="round"/></svg>
</div>
<div class="progress"></div>
</div>
var trackList = [{
title: 'Do or Die',
url: 'https://s3-us-west-2.amazonaws.com/harriscarney/audio/Do+or+Die.mp3',
image: 'https://s3-us-west-2.amazonaws.com/harriscarney/images/Do+or+Die.jpg',
position: '0px'
}, {
title: 'Drop the Game',
url: 'https://s3-us-west-2.amazonaws.com/harriscarney/audio/Drop+the+Game.mp3',
image: 'https://s3-us-west-2.amazonaws.com/harriscarney/images/Drop+the+Game.jpg',
position: -400 * 1 + 'px'
}, {
title: 'Retrograde',
url: 'https://s3-us-west-2.amazonaws.com/harriscarney/audio/Retrograde.mp3',
iamge: 'https://s3-us-west-2.amazonaws.com/harriscarney/images/Retrograde.jpg',
position: -400 * 2 + 'px'
}, {
title: 'Lost in the Moment',
url: 'https://s3-us-west-2.amazonaws.com/harriscarney/audio/Lost+in+the+Moment.mp3',
image: 'https://s3-us-west-2.amazonaws.com/harriscarney/images/Lost+in+the+Moment.jpg',
position: -400 * 3 + 'px'
}, {
title: 'Stay with Me',
url: 'https://s3-us-west-2.amazonaws.com/harriscarney/audio/Stay+with+Me.mp3',
image: 'https://s3-us-west-2.amazonaws.com/harriscarney/images/Stay+with+Me.jpg',
position: -400 * 4 + 'px'
}, {
title: 'Mad World',
url: 'https://s3-us-west-2.amazonaws.com/harriscarney/audio/Mad+World.mp3',
image: 'https://s3-us-west-2.amazonaws.com/harriscarney/images/Mad+World.jpg',
position: -400 * 5 + 'px'
}];
var currentTrack = 0;
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var canvasWidth, canvasHeight;
function canvasSize() {
canvas.width = 500;
canvas.height = 100;
var devicePixelRatio = window.devicePixelRatio || 1;
var backingStoreRatio = context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStoreRatio || 1;
var ratio = devicePixelRatio / backingStoreRatio;
if (devicePixelRatio !== backingStoreRatio) {
var oWidth = 400;
var oHeight = 100;
canvasWidth = oWidth;
canvasHeight = oHeight;
canvas.width = Math.floor(oWidth * ratio);
canvas.height = Math.floor(oHeight * ratio);
canvas.style.width = oWidth + 'px';
canvas.style.height = oHeight + 'px';
context.scale(ratio, ratio);
}
}
var audioContext = new (window.AudioContext || window.webkitAudioContext);
var audio = document.getElementById('audio');
var source = audioContext.createMediaElementSource(audio);
var analyser = audioContext.createAnalyser();
source.connect(analyser);
analyser.connect(audioContext.destination);
var bufferLength = analyser.frequencyBinCount;
var frequencyData = new Uint8Array(bufferLength);
var isPlaying = false;
function Render() {
var fWidth = 5;
var fHeight = 10;
var x = 0;
if (isPlaying) {
analyser.getByteFrequencyData(frequencyData);
}
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.fillStyle = '#00E8FF';
context.beginPath();
for (var i = 0; i < bufferLength; i++) {
fHeight = frequencyData[i] / 3;
if (!isPlaying) {
frequencyData[i] -= frequencyData[i] / 20;
}
context.lineTo(x, canvasHeight - fHeight);
x += fWidth;
}
context.lineTo(canvasWidth, canvasHeight);
context.lineTo(0, canvasHeight);
context.fill();
context.closePath();
document.getElementsByClassName('progress')[0].style.width = (audio.currentTime * 100 / audio.duration).toString() + '%';
requestAnimationFrame(Render);
}
for (var i = 0; i <= trackList.length - 1; i++) {
loadTrack(trackList[i]);
}
for (var p = 0; p <= document.getElementsByClassName('text').length - 1; p++) {
document.getElementsByClassName('text')[p].onclick = function(event) {
if (typeof trackList[currentTrack].object != 'undefined') {
if (!isPlaying) {
if (audio.currentTime !== 0) {
audio.play();
} else {
audio.src = trackList[currentTrack].object;
document.getElementsByClassName('progress')[0].style.background = "url('" + trackList[currentTrack].image + "') 25% 25%";
}
isPlaying = true;
audio.play();
this.innerHTML = 'Pause';
} else {
isPlaying = false;
this.innerHTML = 'Play';
audio.pause();
}
}
}
document.getElementsByClassName('text')[p].onmouseover = function() {
if (isPlaying) {
this.innerHTML = 'Stop music';
} else {
if (typeof trackList[currentTrack].object != 'undefined') {
this.innerHTML = 'Play Music'
} else {
this.innerHTML = 'Loading'
}
}
}
document.getElementsByClassName('text')[p].onmouseout = function() {
this.innerHTML = trackList[currentTrack].title;
}
}
document.getElementsByClassName('next')[0].onclick = function() {
frequencyData = new Uint8Array(bufferLength)
audio.load();
isPlaying = false;
if (currentTrack === trackList.length - 1) {
currentTrack = 0;
} else {
currentTrack++;
}
document.getElementsByClassName('text-container')[0].style.left = trackList[currentTrack].position;
}
document.getElementsByClassName('previous')[0].onclick = function() {
frequencyData = new Uint8Array(bufferLength)
audio.load()
isPlaying = false;
if (currentTrack === 0) {
currentTrack = trackList.length - 1;
} else {
currentTrack--;
}
document.getElementsByClassName('text-container')[0].style.left = trackList[currentTrack].position;
}
function loadTrack(track) {
var request = new XMLHttpRequest();
request.open('GET', track.url, true);
request.responseType = 'blob';
request.onload = function() {
track.object = window.URL.createObjectURL(request.response);
}
request.send();
}
canvasSize();
Render();
@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:900);
body {
overflow: visible;
margin: 0;
}
canvas {
position: absolute;
top: 0;
right: 0;
bottom: 200px;
left: 0;
margin: auto;
}
.container {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
overflow: hidden;
width: 400px;
height: 100px;
margin: auto;
background: #fffff;
box-shadow: 0 20px 50px 0 rgba(0, 100, 200, .5), 0 20px 50px 0 rgba(0, 255, 0, 0.1);
align-items: center;
}
.text-container {
font-size: 0;
position: absolute;
left: 0;
display: inline-block;
width: calc(450px * 6);
height: 100px;
transition: left 0.5s ease-in-out;
}
.text {
-webkit-font-smoothing: antialiased;
font-family: 'Source Sans Pro';
font-size: 30px;
line-height: 100px;
font-weight: 900;
display: inline-block;
overflow: hidden;
width: 400px;
height: 100px;
cursor: pointer;
-webkit-user-select: none;
text-align: center;
text-transform: uppercase;
color: #9e05d1;
-webkit-background-clip: text;
text-shadow: 0 0 0 rgba(0, 0, 255, 0.1);
-webkit-text-fill-color: neon;
}
.text:nth-of-type(1) {
background: url('https://s3-us-west-2.amazonaws.com/harriscarney/images/Do+or+Die.jpg') 25% 25%;
-webkit-background-clip: text;
}
.text:nth-of-type(2) {
background: url(https://s3-us-west-2.amazonaws.com/harriscarney/images/Drop+the+Game.jpg) 25% 25%;
-webkit-background-clip: text;
}
.text:nth-of-type(3) {
background: url(https://s3-us-west-2.amazonaws.com/harriscarney/images/Retrograde.jpg) 25% 25%;
-webkit-background-clip: text;
}
.text:nth-of-type(4) {
background: url(https://s3-us-west-2.amazonaws.com/harriscarney/images/Lost+in+the+Moment.jpg) 60% 60%;
-webkit-background-clip: text;
}
.text:nth-of-type(5) {
background: url(https://s3-us-west-2.amazonaws.com/harriscarney/images/Stay+with+Me.jpg) 25% 25%;
-webkit-background-clip: text;
}
.text:nth-of-type(6) {
background: url(https://s3-us-west-2.amazonaws.com/harriscarney/images/Mad+World.jpg) 80% 80%;
-webkit-background-clip: text;
}
.previous, .next {
z-index: 1;
padding: 20px 10px 20px 10px;
cursor: pointer;
}
.next {
margin-left: auto;
text-align: right;
}
.progress {
position: absolute;
bottom: 0;
left: 0;
height: 7px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment