Skip to content

Instantly share code, notes, and snippets.

@enjikaka
Created February 21, 2015 00:18
Show Gist options
  • Save enjikaka/a3f21d9ebb286029ed36 to your computer and use it in GitHub Desktop.
Save enjikaka/a3f21d9ebb286029ed36 to your computer and use it in GitHub Desktop.
Text Transition Effect
<div class="controls">
<button id="mobile-play">Play</button>
<button id="prev-btn">Previous</button>
<button id="next-btn">Next</button>
</div>
<figure class="stage">
<img id="cover" alt="" />
<div class="wave-wrap"><span class="bar"></span><img class="wave" alt="Waveform"></div>
<figcaption class="mark">
<time datetime="" class="info fade"><span id="album"></span></time>
<p class="description fade"><strong><span id="song"></span> |</strong> <span id="artist"></span></p>
</figcaption>
</figure>
<audio controls></audio>
<div class="search">
<input type="text" placeholder="spotify:track:26HRFRRmtpcpOcFSaZ1Q7f"><br><button>Play URI</button>
</div>
var newSong = false;
var ad = document.querySelector('audio');
var lastPlayed = 0;
var songList = [
'2ytAuyv7c30bvVyZl2Ki5r',
'4x99P1Pmbnlq2vlr8VuwW5',
'0kpMzzaIBW4jUuk7LYsIwl',
'2HIVSk21I9LwzrBvdvpw7K',
'6GRc7PPBY8VtTHvOvgDSuC',
'5DaxyxwFme2H9KKSnBqSJC',
'7JD5OoA5hGBJDCBecoGlCy',
'2eu96dzcqpkvE6Er3NtkZm'
];
var WebAPI = {
tracks: function(id, successCallback, errorCallback) {
var jhr = new JSONHttpRequest();
jhr.onreadystatechange = function() {
if (jhr.readyState === 4) {
try {
if (jhr.responseJSON.error === undefined) {
successCallback(jhr.responseJSON);
} else {
throw new ReferenceError(jhr.responseJSON.error.message);
}
} catch (error) {
alert(error.name + ": " + error.message);
errorCallback(error.name + ": " + error.message);
}
}
};
jhr.open('GET', 'https://api.spotify.com/v1/tracks/' + id, true);
jhr.send();
},
urlToId: function(uri) {
try {
if (uri.indexOf('spotify:') !== -1) {
if (uri.indexOf('spotify:track:') !== -1) {
return uri.split('spotify:track:')[1];
} else {
throw new TypeError('The URI does not belong to a track.');
}
} else if (uri.indexOf('open.spotify.com/') !== -1) {
if (uri.indexOf('open.spotify.com/track/') !== -1) {
return uri.split('open.spotify.com/track/')[1];
} else {
throw new TypeError('The URI does not belong to a track.');
}
} else {
return uri;
}
} catch (error) {
alert(error.name + ':' + error.message);
}
}
};
function genWav(json, ap) {
var url = json.preview_url;
if (url === null) {
alert("Preview not available for this song. :(");
return;
}
document.querySelector('#artist').innerHTML = json.artists[0].name;
document.querySelector('#album').innerHTML = json.album.name; document.querySelector('#song').innerHTML = json.name;
document.querySelector('#cover').src = json.album.images[0].url;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
WaveformGenerator.generate(this.response, window.innerWidth, 80, 'rgba(255,255,255,0.6)', 'bottom', 3, 0.5, function(a,b) {
document.querySelector('.wave-wrap img').src = b;
document.querySelector('.stage').classList.add('hover');
});
document.querySelector('audio').src = URL.createObjectURL(this.response);
document.querySelector('audio').oncanplay = function() {
this.play();
};
newSong = false;
}
};
xhr.send();
}
function playSong(id) {
WebAPI.tracks(id,function(json) {
genWav(json);
}, function(e) {
console.log(e);
});
}
function playPrev() {
document.querySelector('.stage').classList.remove('hover');
lastPlayed -= 1;
var n = songList[lastPlayed];
if (n == undefined) {
playSong(songList[songList.length - 1]);
lastPlayed = songList.length - 1;
return;
}
else {
playSong(n);
}
}
function playNext() {
document.querySelector('.stage').classList.remove('hover');
lastPlayed++;
var n = songList[lastPlayed];
if (n === undefined) {
playSong(songList[0]);
return;
}
else {
playSong(n);
}
}
window.onload = function() {
playSong(songList[0]);
};
document.querySelector('#mobile-play').addEventListener('click', function() {
ad.paused ? ad.play() : ad.pause();
});
ad.addEventListener('play', function() {
document.querySelector('#mobile-play').innerHTML = 'Pause';
});
ad.addEventListener('pause', function() {
document.querySelector('#mobile-play').innerHTML = 'Play';
});
ad.addEventListener('timeupdate', function() {
if (ad.duration - ad.currentTime <= 2) {
document.querySelector('.stage').classList.remove('hover');
}
document.querySelector('.bar').style.left =((ad.currentTime/ad.duration) * 100) + '%';
}, false);
ad.addEventListener('ended', function() {
playNext();
});
document.querySelector('#next-btn').addEventListener('click', function() {
playNext();
});;
document.querySelector('#prev-btn').addEventListener('click', function() {
playPrev();
});;
document.querySelector('.search button').addEventListener('click', function() {
newSong = true; document.querySelector('.stage').classList.remove('hover');
var song = document.querySelector('input').value;
if (song === '') return;
console.log(song + ' -> ' + WebAPI.urlToId(song));
song = song === '' ? 'spotify:track:7JD5OoA5hGBJDCBecoGlCy' : song; WebAPI.tracks(WebAPI.urlToId(song),function(json) {
genWav(json);
}, function(e) {
console.log(e);
});
}, false);
document.querySelector('input').onfocus = function() {
this.select(); document.querySelector('.stage').classList.remove('hover');
};
document.querySelector('input').onblur = function() {
if (!newSong) {
document.querySelector('.stage').classList.add('hover');
}
};
html{
height: 100%;
background: linear-gradient(90deg, #444c4c 0%, #291020 100%) no-repeat fixed;
font-family: 'Ubuntu', sans-serif;
font-weight: 300;
-webkit-font-smoothing: antialiased;
}
body {
padding: 0 20px 20px;
color: #fff;
height:100vh;
overflow:Hidden;
}
a {
color: inherit;
}
strong {
font-weight: 500;
}
h1 {
font-weight: 300;
}
.stage {
position: relative;
background-color:black;
width:100vw;
height:100vh;
margin: 0 -20px 1em;
img#cover {
display: block;
width: 100%;
opacity:0.5;
}
.mark {
position: absolute;
bottom: 115px;
left: 25px;
color: #fff;
font-size: 24px;
}
}
.mark {
display: inline-block;
text-transform: uppercase;
.stage.hover & {
.fade {
-webkit-mask-position-x: 0%;
}
strong {
transform: none;
transition-delay: 0;
}
.description {
transition-delay: 0.75s;
transition-duration: 3s;
}
}
strong {
display: inline-block;
transform: translateY(100%);
transition: transform 1s ease;
transition-delay: 1.5s;
}
p {
margin: 0;
}
.fade {
mask-image: linear-gradient(90deg, #000 0%, #000 33.33%, transparent 66.66%);
-webkit-mask-size: 300%;
-webkit-mask-position-x: 100%;
transition: -webkit-mask-position-x 2s ease;
}
.description {
transition-delay: 0;
}
}
.wave-wrap {
position:fixed;
bottom:0;
left:0;
width:100%;
height:80px;
img {
height:80px;
width:100%;
}
.bar {
content:"";
width:1px;
height:80px;
background-color:white;
display:block;
position:absolute;
top:5px;
right:0;
transform:translateX(1.5px);
z-index:20;
}
}
.search {
position:fixed;
top:10px;
left:25px;
input {
background:none;
width:400px;
font-size:90%;
border:none;
color:rgba(255,255,255,0.9);
outline:none;
transition:width 300ms ease;
&:focus {
border-color:white;
}
border-bottom:1px solid rgba(255,255,255,0.3);
height:41px;
}
}
.controls {
position:fixed;
top:54px;
left:170px;
z-index:999;
}
button {
padding:0.8rem 1rem;
font-size:90%;
min-width:80px;
background:none;
border:1px solid white;
outline:none;
opacity:0.6;
border:1px solid rgba(255,255,255,0.3);
transition:opacity 250ms ease;
border-top-color:rgba(255,255,255,0);
transform:translateY(-1px);
&:hover {
border-color:rgba(255,255,255,0.8);
opacity:1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment