Text transition effect inspired by this youtube video: Game of Thrones Season 5: A Day in the Life (HBO)
Currently Webkit only!
Forked from Daniel Gooß's Pen Text Transition Effect.
A Pen by Jeremy Karlsson on CodePen.
<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; | |
} | |
} |
Text transition effect inspired by this youtube video: Game of Thrones Season 5: A Day in the Life (HBO)
Currently Webkit only!
Forked from Daniel Gooß's Pen Text Transition Effect.
A Pen by Jeremy Karlsson on CodePen.