JSFiddle - React, Tailwind, and code Playground
by pleinx
HTML
<!--
design by: https://www.behance.net/vahanhovh
-->
<nav>
<div class="controls">
Backing track: Shuffle Blues in A
<a class="rewind">
<svg width="26" height="16" viewBox="160 18 26 16" xmlns="http://www.w3.org/2000/svg" class="rewind-icon"><path d="M173.3 26.143l12 6.857V18.778l-12 6.857v-6.857l-12.444 7.11L173.3 33v-6.857z" fill="#A8B5C3" fill-rule="evenodd"/></svg>
</a>
<a class="play">
<svg width="21" height="24" viewBox="210 14 21 24" xmlns="http://www.w3.org/2000/svg" class="play-icon"><path fill="#A8B5C2" fill-rule="evenodd" d="M230.677 25.815L210 37.63V14"/></svg>
<svg width="21px" height="24px" viewBox="210 14 21 24" xmlns="http://www.w3.org/2000/svg" class="pause-icon">
<rect id="pause-1" fill="#A8B5C2" fill-rule="evenodd" x="210" y="14" width="7" height="24"></rect>
<rect id="pause-2" fill="#A8B5C2" fill-rule="evenodd" x="224" y="14" width="7" height="24"></rect>
</svg>
</a>
</div>
<div class="social">
<a href="//www.reddit.com/submit?url=http://codepen.io/gregh/full/zNzvOm/" target="_blank"><i class="fa fa-reddit-alien" aria-hidden="true"></i></a>
<a href="https://twitter.com/intent/tweet?text=Everyone%20can%20play%20the%20blues%20on%20@codepen!%20Record%20your%20solos%20and%20@greghvns%20will%20play%20the%20best%20ones%20on%20a%20real%20guitar&url=http://codepen.io/gregh/full/zNzvOm/" target="_blank"><i class="fa fa-twitter" aria-hidden="true"></i></a>
</div>
</nav>
<div class="loading">
<svg xmlns="http://www.w3.org/2000/svg" width="468" height="153" viewBox="166 91 468 153" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="a" d="M55.185 12.262c-.347.79-.546 1.666-.546 2.62 0 4.574-7.84 53.744-7.84 58.546 0 4.8-2.533 11.727 0 11.727 2.534 0 7.29 1.25 11.385-4.788 4.097-6.037 17.77-29.975 19.23-29.975 1.457 0-7.587 28.44-.427 29.975 4.607.99 11.635-3.858 16.48-8.035.96 5.18 4.9 8.22 13.818 8.22 12.986 0 22.383-13.286 22.383-13.286s.418-3.898-5.88 0c-6.298...
CSS
nav {
background-color: #221C44;
height: 52px;
font-family: 'Roboto', sans-serif;
color: #969DA2;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 40px;
font-size: 14px;
line-height: 17px;
position: relative;
z-index: 2;
.rewind {
margin-left: 28px;
height: 16px;
cursor: pointer;
}
.play {
margin-left: 24px;
height: 24px;
cursor: pointer;
}
.play-icon,
.rewind-icon,
.pause-icon {
&:hover path,
&:hover rect {
fill: #566574;
}
}
.pause-icon {
display: none;
}
.controls {
display: flex;
align-items: center;
}
.social a {
font-size: 24px;
color: #A8B5C2;
margin-left: 18px;
&:hover {
color: #566574;
}
}
}
.loading {
display: flex;
justify-content: center;
margin-top: 24px;
.progress {
transition: width 0.3s linear;
}
position: relative;
z-index: 1;
}
.notes {
display: flex;
height: 0;
opacity: 0;
transition: opacity 1s ease;
justify-content: center;
position: relative;
z-index: 2;
overflow: hidden;
.note {
& > div {
height: 100%;
width: 32px;
border-radius: 16px;
background-color: #D8D8D8;
color: #541F5D;
font-family: 'Roboto', sans-serif;
font-size: 20px;
font-weight: 700;
line-height: 23px;
text-align: center;
box-sizing: border-box;
padding: 5px 0;
box-shadow: 0 7px 8px rgba(0, 0, 0, .16);
}
&:hover div {
background-color: #FF6545;
color: #fff;
}
height: 132px;
&.key{
height: 172px;
& > div {
background-color: #ECDCCA;
}
&:hover > div {
background-color: #FF6545;
color: #fff;
}
}
&:not(:first-child) > div {
margin-left: 8px;
}
&:not(:last-child) > div {
margin-right: 8px;
}
span {
font-size: 0.7em;
}
}
}
.guitar {
width: 96%;
min-width:...
Babel + JSX
class Guitar {
constructor(context, buffer) {
this.context = context;
this.buffer = buffer;
}
setup() {
this.gainNode = this.context.createGain();
this.source = this.context.createBufferSource();
this.source.buffer = this.buffer;
this.source.connect(this.gainNode);
this.gainNode.connect(this.context.destination);
this.gainNode.gain.value = 0.8;
}
play() {
this.setup();
this.source.start(this.context.currentTime);
}
stop() {
this.gainNode.gain.exponentialRampToValueAtTime(0.001, this.context.currentTime + 0.5);
this.source.stop(this.context.currentTime + 0.5);
}
}
class Buffer {
constructor(context, urls) {
this.context = context;
this.urls = urls;
this.buffer = [];
}
loadSound(url, index) {
let request = new XMLHttpRequest();
request.open('get', url, true);
request.responseType = 'arraybuffer';
let thisBuffer = this;
request.onload = function() {
// Safari doesn't support promise based syntax
thisBuffer.context
.decodeAudioData(request.response, function(buffer) {
thisBuffer.buffer[index] = buffer;
updateProgress(thisBuffer.urls.length);
if(index == thisBuffer.urls.length-1) {
thisBuffer.loaded();
}
});
};
request.send();
};
getBuffer() {
this.urls.forEach((url, index) => {
this.loadSound(url, index);
})
}
loaded() {
document.querySelector('.loading').style.opacity = 0;
document.querySelector('.loading').style.height = 0;
document.querySelector('.notes').style.height = "auto";
document.querySelector('.notes').style.opacity = 1;
loaded = true;
starWars();
}
getSound(index) {
return this.buffer[index];
}
}
function playNote() {
let sound = new Sound(context);
let value = this.dataset.frequency;
sound.play(value);
sound.stop();
}
let progressBar =...