diff --git a/app.js b/app.js index 94b6caa..6e5b066 100644 --- a/app.js +++ b/app.js @@ -7,6 +7,7 @@ var muted = false; var audioContext; var audioGainNode; + var backgroundSound; var soundBuffers = { 'tx': null, 'block': null @@ -15,25 +16,6 @@ window.addEventListener('load', init, false); function init() { - try { - window.AudioContext = window.AudioContext||window.webkitAudioContext; - audioContext = new AudioContext(); - audioGainNode = audioContext.createGain(); - audioGainNode.connect(audioContext.destination); - audioGainNode.gain.value = 0.3; - } - catch(e) { - console.error('Web Audio API is not supported in this browser'); - document.getElementById('muteToggle').remove(); - } - try { - loadSound('assets/wood-hit-glass.mp3', 'tx'); - loadSound('assets/whoosh.mp3', 'block'); - } - catch(e) { - console.error('Couldn\'t load sounds.'); - } - if (localStorage) { muted = localStorage.getItem('muted'); if (muted === null) { @@ -47,6 +29,36 @@ muteButton.onclick = toggleMute; + try { + window.AudioContext = window.AudioContext||window.webkitAudioContext; + audioContext = new AudioContext(); + audioGainNode = audioContext.createGain(); + audioGainNode.connect(audioContext.destination); + audioGainNode.gain.value = 0.3; + } + catch(e) { + console.error('Unable to use Web Audio API'); + document.getElementById('muteToggle').remove(); + } + try { + loadSound('assets/whoosh.mp3', 'block'); + loadSound('assets/splash-tiny.mp3', 'tx-sm'); + loadSound('assets/splash-medium.mp3', 'tx-md'); + loadSound('assets/splash-big.mp3', 'tx-lg'); + loadSound('assets/creek.mp3', 'background', function() { + backgroundSound = audioContext.createBufferSource(); + backgroundSound.buffer = soundBuffers['background']; + backgroundSound.connect(audioGainNode); + backgroundSound.loop = true; + if (!muted) { + backgroundSound.start(); + } + }); + } + catch(e) { + console.error('Couldn\'t load sounds.'); + } + socket.on('connect', function() { document.getElementById('connectionStatus').className = 'is-connected'; // Join the room. @@ -62,7 +74,7 @@ }); } - function loadSound(url, bufferName) { + function loadSound(url, bufferName, callback) { var request = new XMLHttpRequest(); request.open('GET', url, true); request.responseType = 'arraybuffer'; @@ -71,6 +83,9 @@ request.onload = function() { audioContext.decodeAudioData(request.response, function(buffer) { soundBuffers[bufferName] = buffer; + if (callback) { + callback(); + } }); console.log('Loaded ' + url + ' as "' + bufferName + '"'); } @@ -88,18 +103,40 @@ source.start(); } + function playbackRate(value, vMin, vMax, oMin, oMax) { + return Math.min(Math.max(oMin, + (Math.log(value) - Math.log(vMin)) / (Math.log(vMax) - Math.log(vMin)) * (oMin - oMax) + oMax + ), oMax); + } + var toggleMute = function() { muted = !muted; if (localStorage) { localStorage.setItem('muted', muted); } muteButton.className = (muted === true ? 'is-muted' : ''); + if (muted) { + backgroundSound.stop(); + } else { + backgroundSound = audioContext.createBufferSource(); + backgroundSound.buffer = soundBuffers['background']; + backgroundSound.connect(audioGainNode); + backgroundSound.loop = true; + backgroundSound.start(); + } } var onTransaction = function(data) { console.log(data); - var playbackRate = Math.min(Math.max(0.25, 2.4 - Math.log(data.valueOut)/5), 7); - playSound('tx', playbackRate); + if (!muted) { + if (data.valueOut < 10) { + playSound('tx-sm', playbackRate(data.valueOut, 0.00001, 10, 0.5, 1.5)); + } else if (data.valueOut < 1000) { + playSound('tx-md', playbackRate(data.valueOut, 10, 1000, 0.25, 1)); + } else if (data.valueOut >= 1000) { + playSound('tx-lg', playbackRate(data.valueOut, 6000, 1000, 0.25, 1)); + } + } var tx = document.createElement('div'); tx.className = 'tx'; var txValue = document.createElement('a'); @@ -109,12 +146,14 @@ txValue.setAttribute('rel', 'noopener'); var txOutputs = document.createElement('div'); txOutputs.className = 'txOutputs'; + txOutputs.style.height = (data.valueOut / 10 + 0.1) + 'em' txValue.appendChild(document.createTextNode(data.valueOut)); tx.appendChild(txValue); tx.appendChild(txOutputs); - var transactions = data.vout.sort(function(a, b) { // sort descending by tx value - return b[Object.keys(b)[0]] - a[Object.keys(a)[0]]; - }); + var transactions = data.vout; +// var transactions = data.vout.sort(function(a, b) { // sort descending by tx value +// return b[Object.keys(b)[0]] - a[Object.keys(a)[0]]; +// }); transactions.forEach(function(value, index, array) { var txOut = document.createElement('div'); var outputSatoshis = value[Object.keys(value)[0]]; @@ -123,7 +162,7 @@ txOut.title = (value[Object.keys(value)[0]] * 0.00000001); txOutputs.appendChild(txOut); }); - if (domRefList.unshift(tx) > 100) { + if (domRefList.unshift(tx) > 300) { var toDelete = domRefList.pop(); toDelete.remove(); } @@ -139,7 +178,7 @@ newBlock.target = '_blank'; newBlock.setAttribute('rel', 'noopener'); newBlock.appendChild(document.createTextNode(data)); - if (domRefList.unshift(newBlock) > 100) { + if (domRefList.unshift(newBlock) > 300) { var toDelete = domRefList.pop(); toDelete.remove(); } diff --git a/assets/creek.mp3 b/assets/creek.mp3 new file mode 100644 index 0000000..8cc19c9 Binary files /dev/null and b/assets/creek.mp3 differ diff --git a/assets/splash-big.mp3 b/assets/splash-big.mp3 new file mode 100644 index 0000000..e3d91d5 Binary files /dev/null and b/assets/splash-big.mp3 differ diff --git a/assets/splash-medium.mp3 b/assets/splash-medium.mp3 new file mode 100644 index 0000000..49653e7 Binary files /dev/null and b/assets/splash-medium.mp3 differ diff --git a/assets/splash-tiny.mp3 b/assets/splash-tiny.mp3 new file mode 100644 index 0000000..438dd89 Binary files /dev/null and b/assets/splash-tiny.mp3 differ diff --git a/style.css b/style.css index f239c3e..5505ab1 100644 --- a/style.css +++ b/style.css @@ -1,5 +1,5 @@ body { - padding: 2em 0 4em; + padding: 0; margin: 0; box-sizing: border-box; font-family: sans-serif; @@ -12,7 +12,6 @@ body { background-color: hsl(208, 73%, 43%); color: white; min-height: 100vh; - overflow: hidden; } * { box-sizing: inherit; @@ -22,7 +21,22 @@ a { text-decoration: none; } #transactionList { - padding: 0 1em; + padding: 1em 0 0; + mix-blend-mode: screen; + opacity: 0.75; + height: 100vh; + overflow: hidden; +} +#transactionList:after { + content: ''; + position: fixed; + bottom: 0; + height: 8em; + left: 0; + right: 0; + background-image: linear-gradient(to top, black, transparent); + z-index: 2; + pointer-events: none; } #connectionStatus.is-connected ~ #transactionList:empty:before { content: 'Waiting for first transaction...'; @@ -33,15 +47,14 @@ a { } .tx { position: relative; - margin: 4px auto; - border-radius: 4px; + margin: 3px auto; width: 20em; min-width: 80%; max-width: 100%; z-index: 1; } .txValue { - display: block; + display: none; flex: 0 0 auto; line-height: 1.25; } @@ -54,18 +67,18 @@ a { .txOut { position: relative; flex: 1 1 auto; - border-bottom: 2px solid white; - border-width: 0 2px 2px 0; - text-align: right; - height: 0.25em; + background-color: white; +} +.txOut:first { + border-left: 3px solid black; } .txOut:after { content: ''; - width: 2px; - height: 0.75em; - background: linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0.5) 80%, white); + width: 3px; + background: black; position: absolute; right: 0; + top: 0; bottom: 0; } @@ -106,6 +119,7 @@ a { transition-delay: 1s; opacity: 0; cursor: pointer; + z-index: 100; } #muteToggle:hover { opacity: 1;