diff options
Diffstat (limited to 'docs/assets')
29 files changed, 889 insertions, 0 deletions
diff --git a/docs/assets/css/css.css b/docs/assets/css/css.css new file mode 100644 index 0000000..6271eb3 --- /dev/null +++ b/docs/assets/css/css.css @@ -0,0 +1,342 @@ +@font-face { + font-family: nhg; + src: url(../fonts/NHaasGroteskTXPro-55Rg.ttf); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: nhg; + src: url(../fonts/NHaasGroteskTXPro-56It.ttf); + font-weight: normal; + font-style: italic; +} +@font-face { + font-family: nhg; + src: url(../fonts/NHaasGroteskTXPro-75Bd.ttf); + font-weight: bold; + font-style: normal; +} +@font-face { + font-family: nhg; + src: url(../fonts/NHaasGroteskTXPro-76BdIt.ttf); + font-weight: bold; + font-style: italic; +} +.desktop .m, +.mobile .d { display: none; } +html, body { + margin: 0; padding: 0; width: 100%; height: 100%; + font-family: nhg, sans-serif; + color: rgba(255,255,255,0.9); +} +html { + background-color: rgb(0,0,0); + background-image: linear-gradient(rgba(20, 10, 0, 0.0), rgba(20, 10, 0, 1.0)); + background-attachment: fixed; + transition: background-color 1s; +} +html.day { + background-color: rgb(80,10,60); +} +html.night { + background-color: rgb(8,10,30); +} +body { + background-color: rgba(0,0,0,0); + transition: background-color 1000ms, opacity 500ms; + opacity: 1; +} +body.loading { + background-color: rgba(255,128,192,1); + background-color: black; + opacity: 0; +} +body.fade { + opacity: 1; + background-color: black; + background-color: rgba(255,128,192,1); +} +.shards { + position: absolute; + top: 0; left: 0; + width: 100%; height: 100%; + overflow: hidden; + pointer-events: none; +} +.bgs { + position: absolute; + top: 50%; left: 50%; + opacity: 0.7; + transition: opacity 500ms; + perspective: 10000px; +} +.stars { + transition: all 500ms cubic-bezier(0,0,0,1); + transform: translateZ(0) scaleX(1) scaleY(1); +} +.stars.fade { + transform: translateZ(0) scaleX(1.03) scaleY(1.03); +} +.fade { + opacity: 0; +} +.bg { + position: absolute; + top: 0; left: 0; + transition: all 120s; +} +header { + background-color: rgba(40,20,30,0.9); + position: absolute; + width: 100%; + bottom: 100px; + left: 0; +} +p { + margin: 0; padding: 0; + line-height: 1.4; +} +p + p { + margin-top: 14px;ß +} +a { + text-decoration: none; + color: rgba(255,255,255,0.8); + transition: color 200ms; + border-bottom: 1px dotted; +} +.desktop a:hover { + color: rgba(255,255,255,1.0); +} +img { + max-width: 100%; +} +img.cover { + max-width: 300px; +} +.menu a { + margin-right: 10px; + border-bottom: 0; +} +.menu a.active { + border-bottom: 1px dotted; + color: rgba(255,255,255,1.0); +} +.logo { + width: 400px; + opacity: 0.8; + animation: fade 10s infinite; +} +.row { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +} +h1 { + font-size: 32px; + margin: 0; + padding: 10px 20px; + letter-spacing: -2px; + text-transform: uppercase; + cursor: pointer; + opacity: 0.9; + transition: opacity 500ms; + color: white; +} +.desktop h1:hover { + opacity: 1; +} +h2 { + margin: 0; + padding: 0 0 15px 0; + letter-spacing: -1px; +} +h3 { + margin: 0; + padding: 0 0 6px 0; + letter-spacing: 1px; + font-weight: normal; + font-style: italic; + font-size: 14px; + text-transform: uppercase; + opacity: 0.7; +} +ul { + margin: 0 0 20px 0; + padding: 0; + list-style-type: none; +} +ul li { + list-style-type: none; + line-height: 1.4; +} +ol { + margin: 0 0 20px 0; + padding: 0; +} +ol li { + line-height: 1.4; +} +.player { + padding: 12px 20px; + width: 300px; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + cursor: pointer; + border-left: 1px solid #000; +} +.player .icon { + width: 1.2em; + height: 1.2em; + background-image: url(../img/pause-inv.png); + background-size: 100%; + background-position: center; + border: 2px solid rgba(255,255,255,0.3); + border-radius: 100%; + margin: 0 10px 0 10px; +} +.player.playing .icon { + background-image: url(../img/pause-inv.png); +} +.player.paused .icon { + background-image: url(../img/play-inv.png); +} +.player .track { + transition: all 100ms; + flex: auto; +} +.desktop .player:hover .track { + color: rgba(255,255,255,1.0); +} +.playlist { + -webkit-overflow-scrolling: touch; + overflow-y: auto; + max-height: calc(100vh - 140px); + width: 331px; + max-width: calc(100vw - 30px); + background: black; + position: absolute; + bottom: 160px; right: 0; + margin: 0px 10px; + padding: 0px; + height: 0; overflow: hidden; + transition: all 0.5s cubic-bezier(0,1,1,1); +} +.playlist.visible { + height: 180px; +} +.playlist ul { + margin: 0; padding: 0; +} +.playlist li { + margin: 0; padding: 10px; + cursor: pointer; + transition: all 0.2s; + background: rgba(20,5,10,0.5); +} +.playlist li.active { + color: #000; + background: rgba(255,255,255,0.9); +} +.playlistToggle { + align-self: flex-end; + width: 15px; + height: 15px; + padding: 10px; + display: flex; + flex-direction: column; + justify-content:space-between; +} +.playlistToggle div { + width: 100%; + height: 2px; + border-bottom: 1px solid #999; + background: white; +} +section { + -webkit-overflow-scrolling: touch; + overflow-y: auto; + max-height: calc(100vh - 140px); + max-width: 500px; + background: black; + position: absolute; + bottom: 160px; left: 0; + margin: 10px 10px; + padding: 10px; + background: rgba(20,5,10,0.5); + pointer-events: none; + opacity: 0; + transition: opacity 200ms; +} +.bio #bio, +.discography #discography, +.hardware #hardware, +.contact #contact { + opacity: 1; + pointer-events: auto; +} +@keyframes fade { + 0% { opacity: 0.6; } + 50% { opacity: 1.0; } + 90% { opacity: 0.7; } +100% { opacity: 0.6; } +} + +@media (max-width: 700px) { + * { box-sizing: border-box; } + header { + bottom: auto; + top: 0px; + } + header .row { + flex-direction: column; + } + header .row .menu { + flex-direction: row; + flex-wrap: wrap; + } + h1 { + flex: 1 1 100%; + text-align: center; + } + .menu a { + display: block; + text-align: center; + margin-left: 6px; + margin-right: 6px; + padding-bottom: 10px; + } + .menu a.active { + border: 0; + } + .playlist { + width: 100vw; + margin: 0; + bottom: 59px; + } + section { + height: calc(100vh - 150px); + width: 100%; + max-width: auto; + min-width: auto; + max-height: auto; + padding-bottom: 20px; + bottom: auto; + top: 90px; + margin: 0; + } + .player { + position: fixed; + bottom: 0; + background: rgba(80,10,60,0.6); + width: 100vw; + padding: 12px 20px; + } + .playlistToggle { + width: 36px; + height: 36px; + } +}
\ No newline at end of file diff --git a/docs/assets/fonts/NHaasGroteskTXPro-55Rg.ttf b/docs/assets/fonts/NHaasGroteskTXPro-55Rg.ttf Binary files differnew file mode 100755 index 0000000..e5ad72b --- /dev/null +++ b/docs/assets/fonts/NHaasGroteskTXPro-55Rg.ttf diff --git a/docs/assets/fonts/NHaasGroteskTXPro-56It.ttf b/docs/assets/fonts/NHaasGroteskTXPro-56It.ttf Binary files differnew file mode 100755 index 0000000..8aa3443 --- /dev/null +++ b/docs/assets/fonts/NHaasGroteskTXPro-56It.ttf diff --git a/docs/assets/fonts/NHaasGroteskTXPro-75Bd.ttf b/docs/assets/fonts/NHaasGroteskTXPro-75Bd.ttf Binary files differnew file mode 100755 index 0000000..d80c0ee --- /dev/null +++ b/docs/assets/fonts/NHaasGroteskTXPro-75Bd.ttf diff --git a/docs/assets/fonts/NHaasGroteskTXPro-76BdIt.ttf b/docs/assets/fonts/NHaasGroteskTXPro-76BdIt.ttf Binary files differnew file mode 100755 index 0000000..81dfad5 --- /dev/null +++ b/docs/assets/fonts/NHaasGroteskTXPro-76BdIt.ttf diff --git a/docs/assets/fonts/alarmclock.ttf b/docs/assets/fonts/alarmclock.ttf Binary files differnew file mode 100755 index 0000000..9e9b593 --- /dev/null +++ b/docs/assets/fonts/alarmclock.ttf diff --git a/docs/assets/fonts/roadrage.ttf b/docs/assets/fonts/roadrage.ttf Binary files differnew file mode 100755 index 0000000..a7699af --- /dev/null +++ b/docs/assets/fonts/roadrage.ttf diff --git a/docs/assets/img/dreaming-city.jpg b/docs/assets/img/dreaming-city.jpg Binary files differnew file mode 100644 index 0000000..211a0a9 --- /dev/null +++ b/docs/assets/img/dreaming-city.jpg diff --git a/docs/assets/img/escape-from-neukoelln.jpg b/docs/assets/img/escape-from-neukoelln.jpg Binary files differnew file mode 100644 index 0000000..dcd1180 --- /dev/null +++ b/docs/assets/img/escape-from-neukoelln.jpg diff --git a/docs/assets/img/pause-button.png b/docs/assets/img/pause-button.png Binary files differnew file mode 100644 index 0000000..6ab7818 --- /dev/null +++ b/docs/assets/img/pause-button.png diff --git a/docs/assets/img/pause-inv.png b/docs/assets/img/pause-inv.png Binary files differnew file mode 100644 index 0000000..9780255 --- /dev/null +++ b/docs/assets/img/pause-inv.png diff --git a/docs/assets/img/pause.png b/docs/assets/img/pause.png Binary files differnew file mode 100644 index 0000000..c2d30ae --- /dev/null +++ b/docs/assets/img/pause.png diff --git a/docs/assets/img/play-button.png b/docs/assets/img/play-button.png Binary files differnew file mode 100644 index 0000000..c0fd3fc --- /dev/null +++ b/docs/assets/img/play-button.png diff --git a/docs/assets/img/play-fill.png b/docs/assets/img/play-fill.png Binary files differnew file mode 100644 index 0000000..2205696 --- /dev/null +++ b/docs/assets/img/play-fill.png diff --git a/docs/assets/img/play-inv.png b/docs/assets/img/play-inv.png Binary files differnew file mode 100644 index 0000000..4baaa5f --- /dev/null +++ b/docs/assets/img/play-inv.png diff --git a/docs/assets/img/play.png b/docs/assets/img/play.png Binary files differnew file mode 100644 index 0000000..b5b4a08 --- /dev/null +++ b/docs/assets/img/play.png diff --git a/docs/assets/img/playbutton.psd b/docs/assets/img/playbutton.psd Binary files differnew file mode 100644 index 0000000..e2dbed4 --- /dev/null +++ b/docs/assets/img/playbutton.psd diff --git a/docs/assets/img/xena-vectra-logo-sm.png b/docs/assets/img/xena-vectra-logo-sm.png Binary files differnew file mode 100644 index 0000000..b42111b --- /dev/null +++ b/docs/assets/img/xena-vectra-logo-sm.png diff --git a/docs/assets/img/xena-vectra-logo.png b/docs/assets/img/xena-vectra-logo.png Binary files differnew file mode 100644 index 0000000..4b3f810 --- /dev/null +++ b/docs/assets/img/xena-vectra-logo.png diff --git a/docs/assets/img/xenavectra.gif b/docs/assets/img/xenavectra.gif Binary files differnew file mode 100644 index 0000000..fb81d57 --- /dev/null +++ b/docs/assets/img/xenavectra.gif diff --git a/docs/assets/js/cielab.js b/docs/assets/js/cielab.js new file mode 100644 index 0000000..14c096f --- /dev/null +++ b/docs/assets/js/cielab.js @@ -0,0 +1,70 @@ +var cielab = (function(){ + var cielab = {} + + var xyz = [0,0,0] + var rgb = [0,0,0] + + L_range = [0, 100] + a_range = [-86.185, 98.254] + b_range = [-107.863, 94.482] + + cielab.gradient = function (n) { + n = n || 100 + var k = 0 + + var L, a, b + + var L0 = randrange(L_range[0] + 50, L_range[1]) + var L1 = randrange(L_range[0]+ 50, L_range[1]) + var a0 = randrange(a_range[0], a_range[1]) + var a1 = randrange(a_range[0], a_range[1]) + var b0 = randrange(b_range[0], b_range[1]) + var b1 = randrange(b_range[0], b_range[1]) + return function next (aa){ + L = mix(k/n, L0, L1) + a = mix(k/n, a0, a1) + b = mix(k/n, b0, b1) + rgb = xyz2rgb(hunterlab2xyz(L, a, b)) + k += 1 + return rgba_string(rgb, aa) + } + } + function rgba_string (rgb, a) { return "rgba(" + rgb.map(Math.round).join(",") + "," + a + ")" } + function hex_string (rgb) { return "#" + rgb.map(Math.round).map(function(n){ var s = n.toString(16); return s.length == 1 ? "0"+s : s }).join("") } + + function mix(n,a,b){ return n*a + (1-n)*b } + function clamp(n,a,b){ return n<a?a:n<b?n:b } + function hunterlab2xyz (L,a,b) { + var_Y = L / 10 + var_X = a / 17.5 * L / 10 + var_Z = b / 7 * L / 10 + + Y = Math.pow(var_Y, 2) + X = ( var_X + Y ) / 1.02 + Z = -( var_Z - Y ) / 0.847 + xyz = [X,Y,Z] + } + function xyz2rgb(){ + var var_X = xyz[0] / 100 //X from 0 to 95.047 (Observer = 2°, Illuminant = D65) + var var_Y = xyz[1] / 100 //Y from 0 to 100.000 + var var_Z = xyz[2] / 100 //Z from 0 to 108.883 + + var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986 + var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415 + var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570 + + if ( var_R > 0.0031308 ) var_R = 1.055 * Math.pow( var_R, 1 / 2.4 ) - 0.055 + else var_R = 12.92 * var_R + if ( var_G > 0.0031308 ) var_G = 1.055 * Math.pow( var_G, 1 / 2.4 ) - 0.055 + else var_G = 12.92 * var_G + if ( var_B > 0.0031308 ) var_B = 1.055 * Math.pow( var_B, 1 / 2.4 ) - 0.055 + else var_B = 12.92 * var_B + + rgb[0] = clamp(var_R * 255, 0, 255) + rgb[1] = clamp(var_G * 255, 0, 255) + rgb[2] = clamp(var_B * 255, 0, 255) + return rgb + } + + return cielab +})()
\ No newline at end of file diff --git a/docs/assets/js/player.js b/docs/assets/js/player.js new file mode 100644 index 0000000..25fdfd6 --- /dev/null +++ b/docs/assets/js/player.js @@ -0,0 +1,79 @@ +const player = (function(){ + let player = {} + let current_index = -1 + let audio = document.createElement('audio') + let tracks = [ + { file: "mp3/xena_vectra-cruise.mp3", title: "Cruise" }, + { file: "mp3/xena_vectra-dreaming_city_2.mp3", title: "Dreaming City 2" }, + { file: "mp3/xena_vectra-escape_from_nk.mp3", title: "Escape from Neukölln" }, + ] + function init(){ + bind() + build() + // play(0) + } + function bind(){ + audio.addEventListener('play', handlePlay) + audio.addEventListener('pause', handlePause) + audio.addEventListener('ended', handleEnded) + document.querySelector('.player .icon').addEventListener('click', togglePlaying) + document.querySelector('.player .track').addEventListener('click', play) + document.querySelector('.player .playlistToggle').addEventListener('click', togglePlaylist) + } + function build() { + tracks.forEach((track, i) => { + let el = document.createElement('li') + el.innerHTML = track.title + el.addEventListener('click', () => { + if (is_mobile) { + hidePlaylist() + } + shards.rebuild() + play(i) + }) + document.querySelector('.playlist ul').appendChild(el) + }) + document.querySelector('.player .track').innerHTML = tracks[0].title + } + function play(n){ + const active = document.querySelector('.playlist ul .active') + if (active) active.classList.remove('active') + document.querySelector('.playlist ul').children[n].classList.add('active') + + current_index = (n + tracks.length) % tracks.length + audio.src = tracks[n].file + audio.play() + document.querySelector('.player .track').innerHTML = tracks[n].title + } + function handlePlay(){ + document.querySelector('.player').classList.add('playing') + document.querySelector('.player').classList.remove('paused') + shards.step() + } + function handlePause(){ + document.querySelector('.player').classList.remove('playing') + document.querySelector('.player').classList.add('paused') + } + function handleEnded(){ + shards.rebuild() + play(current_index+1) + } + function togglePlaying() { + // sounds.play('click') + if (current_index == -1) { + play(0) + } else { + if (audio.paused) audio.play() + else audio.pause() + } + } + function togglePlaylist() { + site.navigateHash('') + document.querySelector('.playlist').classList.toggle('visible') + } + function hidePlaylist() { + document.querySelector('.playlist').classList.remove('visible') + } + init() + return { hidePlaylist } +})()
\ No newline at end of file diff --git a/docs/assets/js/shards.js b/docs/assets/js/shards.js new file mode 100644 index 0000000..1b374ee --- /dev/null +++ b/docs/assets/js/shards.js @@ -0,0 +1,107 @@ +const shards = (function(){ + let count + let delay = 120 * 1000 + let els = [] + let t = 0 + let rebuilding = false + let nextTimeout + let dark, light + const bg_el = document.querySelector('.bgs') + + function init(){ + bind() + build() + step() + setTimeout(next, 20) + bg_el.classList.remove('fade') + } + function bind(){ + document.querySelector('h1').addEventListener('click', () => { + sounds.play('click') + rebuild() + site.navigateHash('') + player.hidePlaylist() + }) + } + function build(){ + count = choice(is_mobile ? [5,7] : [5,7,7,11,11]) + light = cielab.gradient(count) + dark = cielab.gradient(count) + let el + for (var i = 0; i < count; i++) { + el = append(i) + } + } + function destroy(){ + for (var i = 0; i < count; i++) { + els[i] && bg_el.removeChild(els[i]) + } + els.length = 0 + } + function rebuild(){ + if (rebuilding) return + rebuilding = true + // sounds.play('click') + stars.rebuild() + next() + t = 0 + bg_el.classList.add('fade') + setTimeout(() => { + destroy() + build() + step() + setTimeout(next, 20) + bg_el.classList.remove('fade') + rebuilding = false + // sounds.play('click') + }, 500) + } + function append(i){ + const el = document.createElement('div') + el.classList.add('bg') + els.push(el) + bg_el.appendChild(el) + return el + } + function next(){ + clearTimeout(nextTimeout) + nextTimeout = setTimeout(next, delay) + step() + } + function step() { + t += 1 + light = cielab.gradient(count) + let w = { min: is_mobile ? randrange(40, 90) : randrange(20, 40), max: randrange(10, 90) } + if (w.min > w.max) { + w.min += 10 + } + let rot = { min: randint(360), max: randrange(720, 1080) } + for (var i = 0; i < count; i++) { + update(i, t, w, rot, dark, light) + } + document.body.style.backgroundColor = cielab.gradient(2)(0.05) + } + function update(i, t, w, rot){ + const el = els[i] + const n = i / count + const side = lerp(n, w.min, w.max) + const spin = lerp(i % 2 ? (1-n) : (n), rot.min, rot.max) + const rotation = "rotate3d(" + [randrange(-1,1), randrange(-1,1), randrange(-1,1)].join(',') + ',' + randint(360) + "deg)" + el.style.width = side + 'vmin' + el.style.height = side + 'vmin' + el.style.transform = "translate3d(-50%, -50%, 0) rotate(" + spin + "deg) translate3d(50%, 50%, 0) " + rotation + // el.style.transform = "translate3d(-50%, -50%, 0)" + if (t === 1) { + light = cielab.gradient(count) + if (is_mobile) { + el.style.backgroundImage = 'linear-gradient(0deg, ' + dark(1) + ', ' + light(1) + ')' + } else { + el.style.backgroundImage = 'linear-gradient(0deg, ' + dark(1) + ', ' + light(0) + ')' + } + } + el.style.backgroundColor = light(1) + el.style.opacity = lerp(n, randrange(0.1, 0.4), randrange(0.2, 0.5)) + } + init() + return { rebuild: rebuild, step: step, } +})()
\ No newline at end of file diff --git a/docs/assets/js/site.js b/docs/assets/js/site.js new file mode 100644 index 0000000..bff06bb --- /dev/null +++ b/docs/assets/js/site.js @@ -0,0 +1,72 @@ +const site = (function(){ + let section + let links = toArray(document.querySelectorAll('.menu a')) + let time = new Date() + let hour = time.getHours() + let quotes = [ + "So, are softsynths as nasty as they say?", + "Ah, a hardware person, I get it.", + "You have to make space to leave space.", + "Those waveforms are more powerful than we realize.", + "And that sub-oscillator? W-O-W!", + "Get in there, sweep the filter and give yourself a pat on the back. In that order.", + "Not a museum. Move along.", + "I've got to get out of this studio and back out there.", + ] + if (hour < 8 || hour > 16) { + document.body.parentNode.classList.add('night') + } else { + document.body.parentNode.classList.add('day') + } + preload('img/pause-inv.png') + setTimeout(() => { + document.body.classList.remove('loading') + navigateHash(window.location.hash) + const email = atob("eGVuYXZlY3RyYTkwOUBnbWFpbC5jb20=") + const twitter = atob("dmVjdHJheGVuYQ==") + document.querySelector("#email_addr").href = 'mailto:' + email + document.querySelector("#email_addr").innerHTML = email + document.querySelector("#twitter_addr").innerHTML = twitter + document.querySelector("#twitter_addr").href = 'https://twitter.com/' + twitter + }, 0) + toArray(document.querySelectorAll('.menu a')).forEach(a => { + a.addEventListener("click", e => { + e.preventDefault() + sounds.play('click') + console.log(e.target) + if (e.target.nodeName.toLowerCase() !== 'a') { + navigateHash(e.target.parentNode.href) + } else { + navigateHash(e.target.href) + } + }) + }) + function navigateHash(url){ + if (is_mobile) { + player.hidePlaylist() + } + let new_section = (url || "").split('#')[1] + if (section) { + document.body.classList.remove(section) + links.forEach(link => link.classList.remove('active')) + } + if (new_section && new_section !== section) { + if (new_section.match('hardware')) { + document.querySelector('#quote').innerHTML = choice(quotes) + } + document.body.classList.add(new_section) + links.forEach(link => link.getAttribute('href').match(new_section) && link.classList.add('active')) + section = new_section + } else { + section = null + } + // window.location.hash = section || "" + } + function preload(src) { + const img = new Image + img.src = src + } + return { + navigateHash: navigateHash + } +})() diff --git a/docs/assets/js/sounds.js b/docs/assets/js/sounds.js new file mode 100644 index 0000000..39f725d --- /dev/null +++ b/docs/assets/js/sounds.js @@ -0,0 +1,17 @@ +const sounds = (function(){ + let sounds = {} + let els = {} + sounds.add = (fn) => { + const el = document.createElement('audio') + el.src = 'sounds/' + fn + '.mp3' + els[fn] = el + } + sounds.play = (fn) => { + const el = els[fn] + el.currentTime = 0 + el.volume = 0.8 + el.play() + } + sounds.add('click') + return sounds +})() diff --git a/docs/assets/js/stars.js b/docs/assets/js/stars.js new file mode 100644 index 0000000..0637473 --- /dev/null +++ b/docs/assets/js/stars.js @@ -0,0 +1,63 @@ +const stars = (function(){ + var canvas = document.createElement("canvas"), ctx = canvas.getContext('2d') + var s = Math.sin, c = Math.cos + document.addEventListener("DOMContentLoaded", function(){ + document.body.appendChild(canvas) + canvas.classList.add('stars') + canvas.style.width="100%" + canvas.style.height="100%" + canvas.style.position="fixed" + canvas.style.top="0px" + canvas.style.left="0px" + canvas.style.zIndex=-1 + document.body.addEventListener("resize", build) + // document.body.parentNode.style.backgroundColor="black" + ctx.strokeStyle="white" + build() + }) + function ri(n){ return Math.random() * n } + function rr(a,b){ return (b-a) * Math.random() + a } + function build(){ + var w = canvas.width = window.innerWidth * window.devicePixelRatio + var h = canvas.height = window.innerHeight * window.devicePixelRatio + ctx.clearRect(0,0,w,h) + var n = Math.sqrt(w*h)|0 + while (n--) { + var x = ri(w) + var y = ri(h) + var r0 = rr(0, 1) + var r1 = rr(0, 1) + var r2 = rr(0, 1) + var t0 = ri(2*Math.PI) + var t1 = ri(2*Math.PI) + var t2 = ri(2*Math.PI) + var x0 = x+c(t0)*r0 + var y0 = y+s(t0)*r0 + var x1 = x+c(t1)*r1 + var y1 = y+s(t1)*r1 + var x2 = x+c(t2)*r2 + var y2 = y+s(t2)*r2 + ctx.beginPath() + ctx.moveTo(x,y) + ctx.bezierCurveTo(x0,y0,x1,y1,x2,y2) + var color = rr(0, 255)|0 + ctx.strokeStyle="rgb("+color+","+color+","+color+")" + ctx.stroke() + } + } + let rebuilding = false + function rebuild(){ + if (rebuilding) return + rebuilding = true + canvas.classList.add('fade') + document.body.classList.add('fade') + setTimeout(() => { + // destroy() + build() + canvas.classList.remove('fade') + document.body.classList.remove('fade') + rebuilding = false + }, 500) + } + return { rebuild: rebuild } +})()
\ No newline at end of file diff --git a/docs/assets/js/util.js b/docs/assets/js/util.js new file mode 100644 index 0000000..e40db4a --- /dev/null +++ b/docs/assets/js/util.js @@ -0,0 +1,139 @@ +const is_iphone = (navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) +const is_ipad = (navigator.userAgent.match(/iPad/i)) +const is_android = (navigator.userAgent.match(/Android/i)) +const is_mobile = is_iphone || is_ipad || is_android +const is_desktop = !is_mobile; +document.body.parentNode.classList.add(is_desktop ? 'desktop' : 'mobile') + +function avg(a,b,n){ return (a*(n-1) + b)/n } +function rand(n){ return Math.random()*n } +function randint(n) { return ~~(Math.random()*n) } +function randrange(a,b){ return a+rand(b-a) } +function choice(a) { return a[randint(a.length)] } +function clamp(n,a,b) { return a > n ? a : n > b ? b : n } +function sign(n){ return n < 0 ? -1 : 1 } +function mod(n,m){ return n-(m * Math.floor(n/m)) } +function lerp(n,a,b){ return (b-a)*n+a } +function quantize(m,n){ return n * ((m/n)|0) } + +function randgauss (obj, jog) { + var radius = Math.random() * jog + var angle = Math.random() * Math.PI * 2 + obj.left += Math.sin(angle) * radius + obj.top += Math.cos(angle) * radius +} + +function shuffle(a){ + for (var i = a.length; i > 0; i--){ + var r = randint(i) + var swap = a[i-1] + a[i-1] = a[r] + a[r] = swap + } + return a +} + +function toArray (els){ + return Array.prototype.slice.apply(els) +} + +// easing functions +function circular (t) { return Math.sqrt( 1 - ( --t * t ) ) } +function quadratic (t) { return t * ( 2 - t ) } +function back (t) { + var b = 4; + return ( t = t - 1 ) * t * ( ( b + 1 ) * t + b ) + 1; +} +function bounce (t) { + if (t >= 1) return 1; + if ( ( t /= 1 ) < ( 1 / 2.75 ) ) { + return 7.5625 * t * t; + } else if ( t < ( 2 / 2.75 ) ) { + return 7.5625 * ( t -= ( 1.5 / 2.75 ) ) * t + 0.75; + } else if ( t < ( 2.5 / 2.75 ) ) { + return 7.5625 * ( t -= ( 2.25 / 2.75 ) ) * t + 0.9375; + } else { + return 7.5625 * ( t -= ( 2.625 / 2.75 ) ) * t + 0.984375; + } +} +function elastic (t) { + var f = 0.22, + e = 0.4; + + if ( t === 0 ) { return 0; } + if ( t == 1 ) { return 1; } + + return ( e * Math.pow( 2, - 10 * t ) * Math.sin( ( t - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); +} + +function preload (url) { + var img = new Image () + var loaded = false, _cb + img.onload = function(){ + if (loaded) return + loaded = true + if (_cb) { _cb(img) } + } + img.src = url + if (img.complete) { img.onload() } + return { + then: function(cb){ + if (loaded) { cb(img) } + else { _cb = cb } + } + } +} + +function preloadImages () { + var images = toArray(document.getElementById("images").children) + var count = 0, ready = false, _cb + images.forEach(function(img){ + var loaded = false + img.onload = function(){ + if (loaded) return + loaded = true + done(img) + } + if (img.complete) { img.onload() } + }) + function done () { + if (++count == images.length && ! ready) { + ready = true + _cb && _cb() + } + } + return { + then: function(cb){ + if (ready) { cb() } + else { _cb = cb } + } + } +} + +function smoothstep(min,max,n){ + var t = clamp((n - min) / (max - min), 0.0, 1.0); + return t * t * (3.0 - 2.0 * t) +} + +function detrand (x,y) { + return (Math.sin( x * 12.9898 + y * 78.233 ) * 43758.5453) % 1 +} + +function gray_to_transparency(img) { + var canvas = document.createElement("canvas") + var ctx = canvas.getContext('2d') + var nw = img.naturalWidth, nh = img.naturalHeight + canvas.width = nw + canvas.height = nh + ctx.drawImage(img,0,0) + var pixels = ctx.getImageData(0,0,nw,nh) + var data = pixels.data + for (var i = 0, len = nw*nh*4; i < len; i += 4) { + data[i+3] = data[i] + data[i] = data[i+1] = data[i+2] = 255 + } + ctx.putImageData(pixels,0,0) + return canvas +} + +var TWO_PI = 2*Math.PI
\ No newline at end of file diff --git a/docs/assets/sounds/click.mp3 b/docs/assets/sounds/click.mp3 Binary files differnew file mode 100644 index 0000000..37e7df0 --- /dev/null +++ b/docs/assets/sounds/click.mp3 diff --git a/docs/assets/sounds/click.wav b/docs/assets/sounds/click.wav Binary files differnew file mode 100644 index 0000000..7c45aed --- /dev/null +++ b/docs/assets/sounds/click.wav |
