Skip to content

Commit

Permalink
gsuiKeys: huge change, use midi notation instead of keyString
Browse files Browse the repository at this point in the history
  • Loading branch information
mr21 committed Feb 19, 2018
1 parent 6cd8090 commit d7adc5e
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 102 deletions.
27 changes: 14 additions & 13 deletions gsuiKeys/gsuiKeys.css
Expand Up @@ -6,16 +6,21 @@
-ms-user-select: none;
}

.gsuiKey .gsuiKey-row {
display: none;
}
.gsuiKey-row {
position: relative;
box-sizing: border-box;
height: 1em;
}
.gsuiKey-row[data-key$="#"] {
.gsuiKeyBlack-row {
background-color: rgba( 0, 0, 0, .1 );
}
.gsuiKey-row[data-key$="c"],
.gsuiKey-row[data-key$="f"] {
.gsuiKey[data-key="0"],
.gsuiKey[data-key="5"],
.gsuiKey-row[data-key="0"],
.gsuiKey-row[data-key="5"] {
border-bottom: 1px solid rgba( 0, 0, 0, .2 );
}
.gsuiKey-row > div {
Expand All @@ -32,7 +37,7 @@
background-image: linear-gradient( 90deg, #888, #eee );
cursor: default;
}
.gsuiKey[data-key$="#"] {
.gsuiKeyBlack {
position: absolute;
z-index: 1;
width: 65%;
Expand All @@ -41,10 +46,10 @@
border-radius: 0 .1em .1em 0;
background-image: linear-gradient( 90deg, #111, #444 );
}
.gsuiKey[data-key="c"] {
.gsuiKey[data-key="0"] {
background-image: linear-gradient( 90deg, #888, #ccc );
}
.gsuiKey[data-key="c"]:after {
.gsuiKey[data-key="0"]::after {
counter-increment: octave -1;
content: "C" counter( octave );
position: absolute;
Expand All @@ -58,15 +63,11 @@
background-image: linear-gradient( 90deg, #353b52, #7886bd );
}

.gsuiKey[data-key="c"],
.gsuiKey[data-key="f"] {
border-bottom: 1px solid rgba( 0, 0, 0, .2 );
}
.gsuiKey:last-child {
border-bottom: 0;
}
.gsuiKey[data-key="d"],
.gsuiKey[data-key="g"],
.gsuiKey[data-key="a"] {
.gsuiKey[data-key="9"],
.gsuiKey[data-key="7"],
.gsuiKey[data-key="2"] {
height: 2em;
}
28 changes: 14 additions & 14 deletions gsuiKeys/gsuiKeys.html
@@ -1,14 +1,14 @@
<template id="gsuiKeys-octave"
><div class="gsuiKey" data-key="b" ><div data-key="b" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="a#"><div data-key="a#" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="a" ><div data-key="a" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="g#"><div data-key="g#" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="g" ><div data-key="g" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="f#"><div data-key="f#" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="f" ><div data-key="f" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="e" ><div data-key="e" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="d#"><div data-key="d#" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="d" ><div data-key="d" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="c#"><div data-key="c#" class="gsui-row gsuiKey-row"><div></div></div></div
><div class="gsuiKey" data-key="c" ><div data-key="c" class="gsui-row gsuiKey-row"><div></div></div></div
></template>
<div id="gsuiKeys-octave-template"
><div class="gsuiKey" data-key="11"><div data-key="11" class="gsui-row gsuiKey-row" ><div></div></div></div
><div class="gsuiKey gsuiKeyBlack" data-key="10"><div data-key="10" class="gsui-row gsuiKey-row gsuiKeyBlack-row"><div></div></div></div
><div class="gsuiKey" data-key="9" ><div data-key="9" class="gsui-row gsuiKey-row" ><div></div></div></div
><div class="gsuiKey gsuiKeyBlack" data-key="8" ><div data-key="8" class="gsui-row gsuiKey-row gsuiKeyBlack-row"><div></div></div></div
><div class="gsuiKey" data-key="7" ><div data-key="7" class="gsui-row gsuiKey-row" ><div></div></div></div
><div class="gsuiKey gsuiKeyBlack" data-key="6" ><div data-key="6" class="gsui-row gsuiKey-row gsuiKeyBlack-row"><div></div></div></div
><div class="gsuiKey" data-key="5" ><div data-key="5" class="gsui-row gsuiKey-row" ><div></div></div></div
><div class="gsuiKey" data-key="4" ><div data-key="4" class="gsui-row gsuiKey-row" ><div></div></div></div
><div class="gsuiKey gsuiKeyBlack" data-key="3" ><div data-key="3" class="gsui-row gsuiKey-row gsuiKeyBlack-row"><div></div></div></div
><div class="gsuiKey" data-key="2" ><div data-key="2" class="gsui-row gsuiKey-row" ><div></div></div></div
><div class="gsuiKey gsuiKeyBlack" data-key="1" ><div data-key="1" class="gsui-row gsuiKey-row gsuiKeyBlack-row"><div></div></div></div
><div class="gsuiKey" data-key="0" ><div data-key="0" class="gsui-row gsuiKey-row" ><div></div></div></div
></div>
192 changes: 117 additions & 75 deletions gsuiKeys/gsuiKeys.js
Expand Up @@ -5,105 +5,138 @@ function gsuiKeys() {

this._init();
this.rootElement = root;
this.rowElements = [];
this._nlKeys = root.childNodes;
this._nbOct = 0;
root.className = "gsuiKeys";
root.onmousedown = this._evmdRoot.bind( this );
}

gsuiKeys.keyIds = {
"b": 11,
"a#": 10,
"a": 9,
"g#": 8,
"g": 7,
"f#": 6,
"f": 5,
"e": 4,
"d#": 3,
"d": 2,
"c#": 1,
"c": 0
gsuiKeys.keyIds = "c c# d d# e f f# g g# a a# b".split( " " );
gsuiKeys.keyIds.forEach( ( k, i, arr ) => arr[ k ] = i );
gsuiKeys.midiToKeyStr = m => gsuiKeys.keyIds[ m % 12 ] + ~~( m / 12 );
gsuiKeys.keyStrToMidi = k => {
var key = k.substr( 0, k[ 1 ] !== "#" ? 1 : 2 );

return k.substr( key.length ) * 12 + gsuiKeys.keyIds[ key ];
};

gsuiKeys.keyboardToKey = {

// [ relative octave, key index (C = 0, C# = 1) ]
// keyboard down
KeyZ: [ 0, 0 ],
KeyS: [ 0, 1 ],
KeyX: [ 0, 2 ],
KeyD: [ 0, 3 ],
KeyC: [ 0, 4 ],
KeyV: [ 0, 5 ],
KeyG: [ 0, 6 ],
KeyB: [ 0, 7 ],
KeyH: [ 0, 8 ],
KeyN: [ 0, 9 ],
KeyJ: [ 0, 10 ],
KeyM: [ 0, 11 ],
Comma: [ 1, 0 ],
KeyL: [ 1, 1 ],
Period: [ 1, 2 ],
Semicolon: [ 1, 3 ],
Slash: [ 1, 4 ],

// keyboard up
KeyQ: [ 1, 0 ],
Digit2: [ 1, 1 ],
KeyW: [ 1, 2 ],
Digit3: [ 1, 3 ],
KeyE: [ 1, 4 ],
KeyR: [ 1, 5 ],
Digit5: [ 1, 6 ],
KeyT: [ 1, 7 ],
Digit6: [ 1, 8 ],
KeyY: [ 1, 9 ],
Digit7: [ 1, 10 ],
KeyU: [ 1, 11 ],
KeyI: [ 2, 0 ],
Digit9: [ 2, 1 ],
KeyO: [ 2, 2 ],
Digit0: [ 2, 3 ],
KeyP: [ 2, 4 ],
BracketLeft: [ 2, 5 ],
Equal: [ 2, 6 ],
BracketRight: [ 2, 7 ],
};

gsuiKeys.template = document.querySelector( "#gsuiKeys-octave-template" );
gsuiKeys.template.remove();
gsuiKeys.template.removeAttribute( "id" );

gsuiKeys.prototype = {
remove() {
this.empty();
this.rootElement.remove();
this.rowElements.forEach( function( el ) {
},
empty() {
Array.from( this._nlKeys ).forEach( el => {
el.remove();
el._rowElement.remove();
} );
this.rowElements.length = 0;
},
octaves( start, nbOct ) {
var id,
var elRow,
root = this.rootElement,
nbDiff = nbOct - this._nbOct;
maxOct = start + nbOct,
midi = maxOct * 12;

if ( nbDiff || this._octStart !== start ) {
this._octStart = start;
root.style.counterReset = "octave " + ( start + nbOct );
this.empty();
this._octStart = start;
this._nbOct = nbOct;
root.style.counterReset = "octave " + maxOct;
while ( nbOct-- > 0 ) {
root.append.apply( root,
gsuiKeys.template.cloneNode( true ).children );
}
if ( nbDiff ) {
if ( nbDiff > 0 ) {
while ( nbDiff-- > 0 ) {
root.append( document.importNode( gsuiKeys.octaveTemplate.content, true ) );
}
id = this._nbOct * 12;
this.newRowElements = root.querySelectorAll( ".gsui-row" );
this.newRowElements.forEach( function( el ) {
el.remove();
el.dataset.rowid = id++;
} );
Array.prototype.push.apply( this.rowElements, this.newRowElements );
} else {
for ( nbDiff *= 12; nbDiff < 0; ++nbDiff ) {
root.lastChild.remove();
this.rowElements[ this.rowElements.length - 1 ].remove();
this.rowElements.pop();
}
}
this._nbOct = nbOct;
Array.from( root.children ).forEach( elKey => {
elKey._rowElement = elRow = elKey.firstChild;
elRow._keyElement = elKey;
elKey.dataset.midi =
elRow.dataset.midi = --midi;
} );
},
getKeyElementFromMidi( midi ) {
return this._nlKeys[ this._nlKeys.length - 1 - ( midi - this._octStart * 12 ) ];
},
getMidiKeyFromKeyboard( e ) {
var k = gsuiKeys.keyboardToKey[ e.code ];

if ( k ) {
return ( 4 + k[ 0 ] ) * 12 + k[ 1 ];
}
},
keyToIndex( keyStr ) {
var key = keyStr.substr( 0, keyStr[ 1 ] !== "#" ? 1 : 2 );
midiKeyDown( midi ) {
var el = this.getKeyElementFromMidi( midi );

el && el.classList.add( "gsui-active" );
},
midiKeyUp( midi ) {
var el = this.getKeyElementFromMidi( midi );

return keyStr.substr( key.length ) * 12 +
gsuiKeys.keyIds[ key ] - ( this._octStart * 12 );
el && el.classList.remove( "gsui-active" );
},

// private:
_init() {
if ( !gsuiKeys.octaveTemplate ) {
gsuiKeys.octaveTemplate = document.getElementById( "gsuiKeys-octave" );
document.body.addEventListener( "mousemove", function( e ) {
gsuiKeys._focused && gsuiKeys._focused._evmmRoot( e );
} );
document.body.addEventListener( "mouseup", function( e ) {
gsuiKeys._focused && gsuiKeys._focused._evmuRoot( e );
} );
if ( !gsuiKeys._ready ) {
gsuiKeys._ready = true;
document.addEventListener( "mousemove", e => gsuiKeys._focused && gsuiKeys._focused._evmmRoot( e ) );
document.addEventListener( "mouseup", e => gsuiKeys._focused && gsuiKeys._focused._evmuRoot( e ) );
}
},
_isBlack( keyInd ) {
return keyInd === 1 || keyInd === 3 || keyInd === 5 || keyInd === 8 || keyInd === 10;
},
_keydown( keyInd ) {
var elKey = this._nlKeys[ keyInd ];

if ( elKey ) {
this._keyup();
this._keyInd = keyInd;
this._elKey = elKey;
this._octNum = this._octStart + this._nbOct - 1 - ~~( keyInd / 12 );
elKey.classList.add( "gsui-active" );
this.onkeydown && this.onkeydown( elKey.dataset.key, this._octNum, this._gain );
}
},
_keyup() {
if ( this._elKey ) {
this._elKey.classList.remove( "gsui-active" );
this.onkeyup && this.onkeyup( this._elKey.dataset.key, this._octNum, this._gain );
_releaseKeyMouse() {
if ( this._elKeyMouse ) {
this._elKeyMouse.classList.remove( "gsui-active" );
this.onkeyup && this.onkeyup( this._midiKeyMouse, this._gain );
}
},

Expand All @@ -121,20 +154,29 @@ gsuiKeys.prototype = {
}
},
_evmuRoot( e ) {
this._keyup();
delete this._elKey;
delete this._keyInd;
this._releaseKeyMouse();
delete this._elKeyMouse;
delete this._keyIndMouse;
delete gsuiKeys._focused;
},
_evmmRoot( e ) {
var fKeyInd = ( e.clientY - this._rootTop ) / this._blackKeyH,
var elKey,
fKeyInd = ( e.clientY - this._rootTop ) / this._blackKeyH,
iKeyInd = ~~fKeyInd;

if ( e.clientX > this._blackKeyR && this._isBlack( ~~( iKeyInd % 12 ) ) ) {
iKeyInd += fKeyInd - iKeyInd < .5 ? -1 : 1;
}
if ( this._keyInd !== iKeyInd ) {
this._keydown( iKeyInd );
if ( this._keyIndMouse !== iKeyInd ) {
elKey = this._nlKeys[ iKeyInd ];
if ( elKey ) {
this._releaseKeyMouse();
this._keyIndMouse = iKeyInd;
this._elKeyMouse = elKey;
this._midiKeyMouse = +elKey.dataset.midi;
elKey.classList.add( "gsui-active" );
this.onkeydown && this.onkeydown( this._midiKeyMouse, this._gain );
}
}
}
};

0 comments on commit d7adc5e

Please sign in to comment.