Proper (yet more complex) volume calculation. Now changing the volume slider also takes into account the crossfader coef.
This commit is contained in:
34
css/main.css
34
css/main.css
@@ -1,6 +1,7 @@
|
||||
:root {
|
||||
--bg-color: #223;
|
||||
--text-color: #eee;
|
||||
--text-color-light: #bbb;
|
||||
--accent-color-1: #ff91d8;
|
||||
--accent-color-1-light: #ffcdff;
|
||||
--accent-color-2: #ffff7d;
|
||||
@@ -112,16 +113,43 @@ iframe {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
|
||||
.control-label {
|
||||
font-size: 0.8em;
|
||||
|
||||
margin: auto;
|
||||
color: var(--text-color-light);
|
||||
}
|
||||
|
||||
.control-label span {
|
||||
color: var(--accent-color-2);
|
||||
}
|
||||
|
||||
.volume-control {
|
||||
padding-top: 1em;
|
||||
}
|
||||
.volume-control .control-label {
|
||||
width: 5em;
|
||||
padding-top: 1em;
|
||||
/* transform: rotate(270deg); */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.volume-value {
|
||||
color: var(--text-color-light);
|
||||
}
|
||||
|
||||
.speed-control {
|
||||
width: 20%;
|
||||
height: auto;
|
||||
/* margin: auto; */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.speed-control span {
|
||||
font-size: 0.8em;
|
||||
margin: auto;
|
||||
.speed-control .control-label {
|
||||
margin: 0.2em auto;
|
||||
}
|
||||
|
||||
.speed-slider {
|
||||
|
14
index.html
14
index.html
@@ -32,17 +32,23 @@
|
||||
<iframe id="playerA" src="" width="480" height="270", frameborder='0'></iframe>
|
||||
<input class='load-button' type="button" value="Load new track or playlist">
|
||||
<div class="speed-control">
|
||||
<span class='speed-value'></span>
|
||||
<input type="range" class='speed-slider' name="speedRate" value="1" min='0.25' max='2' step='0.25'>
|
||||
<p class='control-label'>Speed: <span class='speed-value'></span></p>
|
||||
</div>
|
||||
<div class="volume-control">
|
||||
<input type="range" class='volume-slider' min='0' max = '100' value="80">
|
||||
<p class='control-label'>Vol: <span class="volume-slider-value"></span> (<span class="volume-value"></span>)</p>
|
||||
</div>
|
||||
<input type="range" class="volume-slider" min='0' max = '100' value="80">
|
||||
</div>
|
||||
<div class="player">
|
||||
<iframe id="playerB" src="" width="480" height="270", frameborder='0'></iframe>
|
||||
<input type="range" class='volume-slider' min='0' max = '100' value="80">
|
||||
<div class="volume-control">
|
||||
<input type="range" class='volume-slider' min='0' max = '100' value="80">
|
||||
<p class='control-label'>Vol: <span class="volume-slider-value"></span> (<span class="volume-value"></span>)</p>
|
||||
</div>
|
||||
<div class="speed-control">
|
||||
<span class='speed-value'></span>
|
||||
<input type="range" class='speed-slider' name="speedRate" value="1" min='0.25' max='2' step='0.25'>
|
||||
<p class='control-label'>Speed: <span class='speed-value'></span></p>
|
||||
</div>
|
||||
<input class='load-button' type="button" value="Load new track or playlist">
|
||||
</div>
|
||||
|
99
js/main.js
99
js/main.js
@@ -4,27 +4,26 @@ tag.src = 'https://www.youtube.com/iframe_api';
|
||||
let firstScriptTag = document.getElementsByTagName('script')[0];
|
||||
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
||||
|
||||
//THE DJ CROSSFADER!!!
|
||||
let crossfader = document.querySelector('#crossfader');
|
||||
|
||||
class player {
|
||||
trackID;
|
||||
// volume;
|
||||
// id;
|
||||
// iframe;
|
||||
player;
|
||||
// node;
|
||||
crossfaderCoef;
|
||||
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
this.iframe = document.querySelector('#'+this.id);
|
||||
// console.log('#'+this.id);
|
||||
// console.log(this.iframe);
|
||||
// this.volume = vol;
|
||||
|
||||
this.node = this.iframe.parentNode;
|
||||
this.volume = this.node.querySelector('.volume-slider').value;
|
||||
this.volSliderVal = this.node.querySelector('.volume-slider-value');
|
||||
this.volVal = this.node.querySelector('.volume-value')
|
||||
this.volSliderVal.innerHTML = this.volume + '%';
|
||||
this.loadButton = this.node.querySelector('.load-button');
|
||||
this.speedSlider = this.node.querySelector('.speed-slider');
|
||||
this.speedSlider.previousElementSibling.innerHTML = 'Speed: ' + this.speedSlider.value;
|
||||
this.speedSlider.nextElementSibling.querySelector('.speed-value').innerHTML = this.speedSlider.value;
|
||||
}
|
||||
|
||||
init(trackID) {
|
||||
@@ -40,17 +39,12 @@ class player {
|
||||
});
|
||||
}
|
||||
onPlayerReady(e) {
|
||||
// console.log(e.target);
|
||||
// this.node.querySelector('.volumeSlider').value = this.player.getVolume();
|
||||
// e.target.playVideo();
|
||||
// console.log(e.target);
|
||||
// e.target.setVolume(this.volume);
|
||||
this.player.setVolume(this.volume);
|
||||
|
||||
this.node.querySelector('.volume-slider').addEventListener('input', (e) => {
|
||||
let volume = e.target.value;
|
||||
this.volume = volume;
|
||||
this.player.setVolume(volume);
|
||||
this.volume = e.target.value;
|
||||
this.volSliderVal.innerHTML = this.volume + '%';
|
||||
this.volumeUpdate();
|
||||
});
|
||||
|
||||
this.loadButton.addEventListener('click', () => {
|
||||
@@ -72,11 +66,11 @@ class player {
|
||||
});
|
||||
|
||||
this.speedSlider.addEventListener('input', (e) => {
|
||||
this.speedSlider.previousElementSibling.innerHTML = 'Speed: ' + e.target.value;
|
||||
this.speedSlider.nextElementSibling.querySelector('.speed-value').innerHTML = e.target.value;
|
||||
this.player.setPlaybackRate(Number(e.target.value));
|
||||
});
|
||||
|
||||
// updateCrossfader(crossfader.value); //Throws an error at the beginning because the second player is not ready yet.
|
||||
this.volumeUpdate();
|
||||
}
|
||||
|
||||
onPlayerStateChange(e) {
|
||||
@@ -103,6 +97,12 @@ class player {
|
||||
});
|
||||
}
|
||||
|
||||
volumeUpdate() {
|
||||
let outputVolume = Math.round(this.volume * this.crossfaderCoef);
|
||||
this.player.setVolume(outputVolume);
|
||||
this.volVal.innerHTML = outputVolume + '%';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -116,38 +116,65 @@ function onYouTubeIframeAPIReady() {
|
||||
playerB.init('PhEuAuhH418');
|
||||
}
|
||||
|
||||
// while (bothPlayersReady < 2) {
|
||||
//
|
||||
// }
|
||||
crossfader.addEventListener('input', (e) => {
|
||||
calcCrossfaderCoefs(crossfader.value);
|
||||
|
||||
crossfader.addEventListener('input', (e) => {
|
||||
//Makes the slider stick on the middle
|
||||
if (Math.abs(crossfader.value - 500) < 15) {
|
||||
crossfader.value = 500;
|
||||
}
|
||||
|
||||
updateCrossfader(crossfader.value);
|
||||
calcCrossfaderCoefs(crossfader.value);
|
||||
|
||||
let boxShadowStyle = '0 0 3em #ddbddd'
|
||||
playerA.iframe.style.boxShadow = boxShadowStyle + componentToHex(Math.round(playerA.crossfaderCoef*255));
|
||||
playerB.iframe.style.boxShadow = boxShadowStyle + componentToHex(Math.round(playerB.crossfaderCoef*255));
|
||||
|
||||
playerA.volumeUpdate();
|
||||
playerB.volumeUpdate();
|
||||
|
||||
// updateCrossfader(crossfader.value);
|
||||
});
|
||||
|
||||
//
|
||||
function calcCrossfaderCoefs(input) {
|
||||
let normVal = input / 1000;
|
||||
|
||||
|
||||
function updateCrossfader(input) {
|
||||
let normVal = crossfader.value / 1000;
|
||||
|
||||
// let coefB = normVal ** 2;
|
||||
// let coefA = (1 - normVal) ** 2;
|
||||
//Classic 'transition' curve
|
||||
let coefB = Math.min(normVal*2, 1);
|
||||
let coefA = Math.min((1-normVal)*2, 1);
|
||||
|
||||
//Cheap smooth curve
|
||||
// let coefB = normVal ** 2;
|
||||
// let coefA = (1 - normVal) ** 2;
|
||||
|
||||
// Sets box-shadow transparency depending on crossfader position
|
||||
let boxShadowStyle = '0 0 3em #ddbddd'
|
||||
playerA.iframe.style.boxShadow = boxShadowStyle + componentToHex(Math.round(coefA*255));
|
||||
playerB.iframe.style.boxShadow = boxShadowStyle + componentToHex(Math.round(coefB*255));
|
||||
//Amplitude-preserving curve (but not power)
|
||||
// let coefB = (normVal ** 2) * (3 - 2 * normVal);
|
||||
// let coefA = 1 - coefB;
|
||||
|
||||
playerA.player.setVolume(playerA.volume * coefA);
|
||||
playerB.player.setVolume(playerB.volume * coefB);
|
||||
// return [coefA, coefB];
|
||||
playerA.crossfaderCoef = coefA;
|
||||
playerB.crossfaderCoef = coefB;
|
||||
}
|
||||
//
|
||||
|
||||
|
||||
// function updateCrossfader(input) {
|
||||
// let normVal = crossfader.value / 1000;
|
||||
//
|
||||
// // let coefB = normVal ** 2;
|
||||
// // let coefA = (1 - normVal) ** 2;
|
||||
// let coefB = Math.min(normVal*2, 1);
|
||||
// let coefA = Math.min((1-normVal)*2, 1);
|
||||
//
|
||||
//
|
||||
// // Sets box-shadow transparency depending on crossfader position
|
||||
// let boxShadowStyle = '0 0 3em #ddbddd'
|
||||
// playerA.iframe.style.boxShadow = boxShadowStyle + componentToHex(Math.round(coefA*255));
|
||||
// playerB.iframe.style.boxShadow = boxShadowStyle + componentToHex(Math.round(coefB*255));
|
||||
//
|
||||
// playerA.player.setVolume(playerA.volume * coefA);
|
||||
// playerB.player.setVolume(playerB.volume * coefB);
|
||||
// }
|
||||
|
||||
// From https://thomaspark.co/projects/needledrop/ by Thomas Park
|
||||
// function getYouTubeID(url){
|
||||
|
Reference in New Issue
Block a user