<header>
<button id="play-pause" data-playing="false"><i class="fa fa-play"></i></button>
<label>This is a javascript lab created by <a href="http://futuristicandco.org" target="new">Kamogelo Matshego</a></label>
</header>
<div class="container player"></div>
<audio id="1" src="https://freewavesamples.com/files/Bass-Drum-1.wav"></audio>
<audio id="2" src="https://freewavesamples.com/files/Ensoniq-ESQ-1-Snare.wav"></audio>
<audio id="3" src="https://freewavesamples.com/files/Closed-Hi-Hat-1.wav"></audio>
<audio id="4" src="https://freewavesamples.com/files/Ensoniq-SQ-1-Open-Hi-Hat.wav"></audio>
<audio id="5" src="https://freewavesamples.com/files/Floor-Tom-1.wav"></audio>
*, *::before, *::after {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
*:before, *:after {
content: '';
}
html, body {
margin: 0px;
padding: 0px;
}
body {
background: #16181C;
font-family: 'Open Sans', sans-serif;
}
div {
display: block;
position: relative;
}
header {
width: 1300px;
height: auto;
padding: 50px 0px;
margin: 0px auto;
position: relative;
}
header label {
color: white;
font-size: 12px;
margin-left: 20px;
}
header label a {
color: #60B5D1;
}
.container {
left: 50%;
z-index: 0;
float: left;
width: 1100px;
height: auto;
margin-left: 100px;
max-height: 100vh;
position: relative;
border: 8px solid #16181C;
transform: translateX(-50%);
}
.row {
float: left;
clear: both;
width: 100%;
height: auto;
max-width: 100%;
border-bottom: 8px solid #16181C;
}
.row::before {
top: 0px;
left: -208px;
width: 200px;
height: 100%;
position: absolute;
letter-spacing: 1px;
border-radius: 2px;
background: rgba(0, 0, 0, 0.025);
border-right: 8px solid #16181C;
box-shadow: inset 0px 0px 0px 1px rgba(0, 0, 0, 0.65),
inset 0px 0px 0px 2px rgba(255, 255, 255, 0.035),
inset 0px 5px 20px -10px rgba(255, 255, 255, 0.25),
inset 0px -5px 20px -10px black;
}
.row::after {
top: 15%;
left: -198px;
width: 172px;
height: 70%;
line-height: 8px;
z-index: 1;
padding: 15px;
position: absolute;
font-family: 'Open Sans';
font-weight: 300;
text-transform: uppercase;
color: rgba(255,255,255,0.35);
font-size: 11px;
border-radius: 2px;
background: #101114;
border: 1px solid rgba(0, 0, 0, 0.5);
box-shadow: inset 0px 0px 0px 1px rgba(255, 255, 255, 0.035),
inset 0px -20px 20px -20px rgba(0, 0, 0, 0.5),
inset 0px 20px 20px -20px rgba(255, 255, 255, 0.05);
}
.row:nth-child(1)::after {
content: 'Drum Kick';
}
.row:nth-child(2)::after {
content: 'Drum Snare';
}
.row:nth-child(3)::after {
content: 'Drum Hi-Hat';
}
.row:nth-child(4)::after {
content: 'Drum Hi-Hat 2';
}
.row:nth-child(5)::after {
content: 'Drum Tom';
}
.sample {
float: left;
border-radius: 2px;
display: inline-block;
background: rgba(0, 0, 0, 0.025);
border-right: 8px solid #16181C;
box-shadow: inset 0px 0px 0px 1px rgba(0, 0, 0, 0.65),
inset 0px 0px 0px 2px rgba(255, 255, 255, 0.035),
inset 0px 5px 20px -10px rgba(255, 255, 255, 0.25),
inset 0px -5px 20px -10px black;
}
.sample:nth-child(8n+6)::after {
top: 1px;
left: 1px;
z-index: -1;
opacity: 0.05;
border-radius: 2px;
background: #FF7B5F;
position: absolute;
width: calc(400% + 22px);
height: calc(100% + 0px);
}
.sample::before {
top: 15%;
left: 15%;
width: 70%;
height: 70%;
z-index: 1;
position: absolute;
border-radius: 2px;
background: #101114;
border: 1px solid rgba(0, 0, 0, 0.5);
box-shadow: inset 0px 0px 0px 1px rgba(255, 255, 255, 0.035),
inset 0px -20px 20px -20px rgba(0, 0, 0, 0.5),
inset 0px 20px 20px -20px rgba(255, 255, 255, 0.05);
}
.sample:active::before,
.sample:focus::before {
background: #0C0D0F;
box-shadow: inset 0px 0px 0px 1px rgba(255, 255, 255, 0.035),
inset 0px 20px 20px -20px rgba(0, 0, 0, 0.5),
inset 0px 20px 20px -20px rgba(255, 255, 255, 0.05);
}
.sample.active::before {
background: #DB6B53;
border: 1px solid rgba(255, 255, 255, 0.035);
box-shadow: inset 0px 0px 0px 1px rgba(0, 0, 0, 0.05),
inset 0px -20px 20px -20px rgba(0, 0, 0, 0.85),
inset 0px 20px 20px -20px rgba(255, 255, 255, 0.05);
}
.sample.active.hit::before {
background: #DB6B53;
border: 1px solid rgba(255, 255, 255, 0.15);
box-shadow: 0px 0px 20px 1px #DB7E53,
inset 0px 0px 0px 1px rgba(0, 0, 0, 0.05),
inset 0px -20px 20px -20px rgba(0, 0, 0, 1),
inset 0px 20px 20px -20px rgba(255, 255, 255, 1);
}
.sample.active.disabled.hit::before {
background: #DBBBB0;
border: 1px solid rgba(255, 255, 255, 0.035);
box-shadow: inset 0px 0px 0px 1px rgba(0, 0, 0, 0.05),
inset 0px -20px 20px -20px rgba(0, 0, 0, 0.85),
inset 0px 20px 20px -20px rgba(255, 255, 255, 0.05);
}
.sample.active.disabled::before {
opacity: 0.35;
background: #DBBBB0;
}
.enable-disable-row {
top: 50%;
left: -60px;
width: 14px;
height: 14px;
outline: none;
border: none;
z-index: 2;
margin-top: -7px;
background: #81B55B;
position: absolute;
border-radius: 50%;
box-shadow: 0px 0px 0px 2px rgba(0, 0, 0, 0.5),
0px 0px 0px 3px rgba(255, 255, 255, 0.15),
0px 0px 0px 4px rgba(0, 0, 0, 0.5),
inset 0px 0px 5px -1px white;
}
.enable-disable-row.disabled {
background: #CF472F;
}
/**
* Javascript Mixtape Drum Machine
* @author Kamogelo Matshego
* @version 1.0.0
* @desc This is a javascript lab created
* to demonstrate music patterns in the web browser.
* I started this project just for fun and intend on
* adding more to it and keeping this pen updated.
* All drum samples were provided by 99Samples:
* http://99sounds.org/drum-samples/
*/
(function(DrummerJS, $, undefined) {
'use strict';
// ======================================
// establish public variables and methods
// ======================================
DrummerJS.title = 'Javascript Drum Machine';
DrummerJS.description = 'Create audio loops using drum samples.'
DrummerJS.author = 'Kamogelo Matshego';
var $_container = $('.player');
var $_containerWidth = $_container.width();
var $_containerHeight = $_container.height();
var $_setBPM = $('#set-bpm');
var $_playPauseBtn = $('#play-pause');
var $_setSamplesBtn = $('#set-samples');
var $_toggleRowBtn;
var $_sampleBtn;
var _urlHash;
var _sampleList = 'default';
var _totalSteps = 16;
var _totalRows = 5;
var _currentStep = 1;
var _sampleRate = 44100;
var _minuteInSeconds = 60;
var _beatsPerMinute = 140;
var _stepDelay;
var calculateBPM = function() {
_stepDelay = Math.round(((_sampleRate * _minuteInSeconds) / (_beatsPerMinute * _totalSteps)) / _totalSteps);
return _stepDelay;
};
// =======================================================
// creates namespace provider which helps isolate
// implementated code from the global namespace, providing
// a single point of access for functions and methods.
// =======================================================
// this keeps the code more organized and allows the code
// to be combined into more logical sections.
// =======================================================
DrummerJS.handler = (function() {
function _handler() {
/**
* @var _this
* @desc in a 'non-strict' environment, 'this' is bound to
* the global scope (if it hasn't been bound to anything else).
* in 'strict' mode it is set to undefined. we store it in a
* variable to avoid scope conflicts.
*/
var _this = this;
var _isPlaying;
this.playPauseHandler = function(button) {
calculateBPM();
var status = button.data('playing');
if(status === 'true') {
button.data('playing', 'false').html('<i class="fa fa-play"></i>');
_this.stopAudio();
}else {
button.data('playing', 'true').html('<i class="fa fa-pause"></i>');
_this.startAudio();
}
};
this.pageLoad = function() {
if(!window.location.hash) {
window.location.hash = '!/';
}
_urlHash = window.location.hash.split('/');
};
this.toggleSample = function(sample) {
sample.toggleClass('active');
};
this.toggleSampleHandler = function() {
$('.sample').on('click', function() {
_this.toggleSample($(this));
});
};
this.updateSampleList = function(samples) {
_sampleList = samples;
console.log(_sampleList);
};
this.updateBPM = function(bpm) {
_beatsPerMinute = bpm;
calculateBPM();
_this.stopAudio();
_this.startAudio();
};
this.stopAudio = function() {
$_sampleBtn.removeClass('hit');
clearInterval(_isPlaying);
};
this.startAudio = function() {
_isPlaying = window.setInterval(function() {
_this.playAudio()
}, _stepDelay);
}
this.playAudio = function() {
if(_currentStep < _totalSteps) {
_currentStep++;
}else if(_currentStep >= _totalSteps){
_currentStep = 1;
}
$_sampleBtn.removeClass('hit');
for(var i = 1; i < _totalRows + 1; i++) {
var $_newSample = $('.sample[data-row="' + i + '"][data-column="' + _currentStep + '"]');
if($_newSample.hasClass('active')) {
$('#' + i)[0].currentTime = 0;
if(!$_newSample.hasClass('disabled')) {
$('#' + i)[0].play();
}else{
$('#' + i)[0].pause();
}
$_newSample.addClass('hit');
}
}
};
this.createMatrix = function(rows, columns) {
var sampleSize = $_containerWidth / columns;
for(var i = 1; i < rows + 1; i++) {
$('<div class="row" id="row-' + i + '"></div>').appendTo('.container');
$('<button class="enable-disable-row" id="toggle-row-' + i + '"></button>').prependTo('#row-' + i);
for(var k = 1; k < columns + 1; k++) {
$('<div class="column sample" data-row="' + i + '" data-column="' + k + '" style="height:' + (sampleSize - 8) + 'px;width:' + sampleSize + 'px"></div>').appendTo('#row-' + i);
}
}
$_toggleRowBtn = $('.enable-disable-row');
$_sampleBtn = $('.sample');
calculateBPM();
};
this.toggleRowBtnHandler = function(button) {
button.toggleClass('disabled');
var rowID = button.attr('id').replace('toggle-row-', '');
$('.sample[data-row="' + rowID + '"]').toggleClass('disabled');
};
/**
* @function init()
* @desc initiates the DrummerJS global function
* creating an active instance of the script on the
* current site.
*/
this.init = function() {
// run functions here
_this.pageLoad();
_this.createMatrix(_totalRows, _totalSteps);
_this.toggleSampleHandler();
$_playPauseBtn.on('click', function() {
_this.playPauseHandler($(this));
});
$_toggleRowBtn.on('click', function() {
_this.toggleRowBtnHandler($(this));
});
$_setBPM.on('change', function() {
_this.updateBPM($(this).val());
});
$_setSamplesBtn.on('change', function() {
_this.updateSampleList($(this).val());
});
// start the drum machine
$_playPauseBtn.click();
return this;
};
// initiate the script!
return this.init();
}
// create a new handler object
return new _handler();
}());
// assign DrummerJS to the global namespace
}(window.DrummerJS = window.DrummerJS || {}, jQuery));
No comments:
Post a Comment