diff --git a/public/index.html b/public/index.html index 5e9aa23..c2c9394 100755 --- a/public/index.html +++ b/public/index.html @@ -2,67 +2,13 @@ + CodePen - Globe - - - Your Mycelial Network - - - - - - - - - - - - -
-
-

Myco.Systems

- -
-
-
Donate
+ -
-
- -
-
-
- wallet.name -
-
-
-
-
-
-
- Address: - - -
-
-
-
- - - - - + \ No newline at end of file diff --git a/public/script.js b/public/script.js index bca7241..2ca669f 100755 --- a/public/script.js +++ b/public/script.js @@ -1,421 +1,111 @@ -// +(function () { + "use strict"; -var donateButton = document.getElementById("donateButton"); -var card = document.getElementById("card"); + // braille -donateButton.addEventListener("click", function (event) { - event.stopPropagation(); - if (card.classList.contains("card-out")) { - card.classList.remove("card-out"); - card.classList.add("card-in"); - } else { - card.classList.remove("card-in"); - card.classList.add("card-out"); - } -}); + const enc = (x) => + ((x & 0x08) << 3) | ((x & 0x70) >> 1) | (x & 0x87) | 0x2800; + const row = (x) => String.fromCharCode(...Array.from(x, enc)); -window.addEventListener("click", function (event) { - if (event.target === card || card.contains(event.target)) { - return; - } + const create = (width, height) => + Array.from(Array(height >> 2), () => new Uint8Array(width >> 1)); - if (card.classList.contains("card-in")) { - card.classList.remove("card-in"); - card.classList.add("card-out"); - } -}); + const set = (table, x, y) => + (table[y >> 2][x >> 1] |= 1 << ((y & 3) | ((x & 1) << 2))); -var cryptoWallets = [ - { - symbol: "XMR", - name: "Monero", - address: - "49r2aeun8DtV5VqZpZSwRpS83WfUWEaLt4NG8HJwwVkbiT1vSsXTXrPFKkKTdc6MPX9iezbTidNPvhGZKCnM1338TfK6Hgi" - }, - { - symbol: "LTC", - name: "Litecoin", - address: "LRAm7h5XENknfYEpbdVsvyGY8D6MiXGTDV" - }, - { - symbol: "BTC", - name: "Bitcoin", - address: "bc1qkv97ajh7f0a72l9rsjd3fmmly5q5uywr06q3x0" - } -]; + const render = (table) => table.map(row).join("\n"); -var walletsContainer = document.getElementById("wallets"); -var qrImage = document.getElementById("qrImage"); -var donateTitle = document.getElementById("donateTitle"); -var donateWarn = document.getElementById("donateWarn"); -var walletAddress = document.getElementById("walletAddress"); -var copyButton = document.getElementById("copyButton"); + // util -function selectWallet(symbol) { - var wallet = cryptoWallets.find(function (w) { - return w.symbol === symbol; - }); - if (!wallet) return; + const frame = () => new Promise((resolve) => requestAnimationFrame(resolve)); - var buttons = Array.from(walletsContainer.children); - buttons.forEach(function (button) { - button.classList.remove("active"); - if (button.textContent === symbol) { - button.classList.add("active"); + const element = (name, options) => + Object.assign(document.createElement(name), options); + + // bayer + + const bayer = (order, x, y) => { + let z = 0; + for (let i = order; i--; x >>= 1, y >>= 1) + z = ((((x & 1) ^ (y & 1)) | (z << 1)) << 1) | (y & 1); + return z; + }; + + const lut = (order) => { + const size = 1 << order, + area = size * size; + const lut = new Float32Array(area); + for (let y = 0; y < size; y++) + for (let x = 0; x < size; x++) + lut[x + y * size] = (bayer(order, x, y) + 0.5) / area; + return (x, y) => lut[(x % size) + (y % size) * size]; + }; + + // render + + const simplex = new SimplexNoise(); + const bayer4 = lut(4); + + const fbm = (freq, amp, x, y, z) => + simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) + + simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) + + simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) + + simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) + + simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) + + simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) + + simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2) + + simplex.noise3D(x * (freq *= 2), y * freq, z * freq) * (amp /= 2); + + const texture = (u, v, w) => (2 * (0.5 + 0.5 * fbm(0.5, 1, u, v, w))) % 1; + + const globe = (x, y, u, v, w) => { + const d = u * u + v * v; + if (d > 1) return false; + + const f = 1 / ((1 - d ** 0.5) ** 0.5 + 1); + const t = texture(1e-1 * w + f * u, f * v, 1e-2 * w); + return t > bayer4(x, y); + }; + + // main + + const main = async () => { + const fillerSize = 100; + const filler = + "\u28ff".repeat(fillerSize) + "\n\u28ff".repeat(fillerSize - 1); + + const root = element("div", { className: "braille" }); + const hidden = element("div", { className: "hidden", textContent: filler }); + const visible = element("div", { className: "visible" }); + + root.appendChild(hidden); + root.appendChild(visible); + document.body.appendChild(root); + + for (; ; await frame()) { + const hr = hidden.getBoundingClientRect(); + const fontWidth = hr.width / fillerSize; + const fontHeight = hr.height / fillerSize; + + const rr = root.getBoundingClientRect(); + const ratio = rr.width / rr.height; + const width = (rr.width / fontWidth) << 2; + const height = (rr.height / fontHeight) << 3; + + const pixels = create(width, height); + const time = 1e-3 * Date.now(); + + for (let y = 0; y < height; y++) { + const v = (2 * y) / height - 1; + for (let x = 0; x < width; x++) { + const u = ratio * ((2 * x) / width - 1); + if (globe(x, y, u, v, time)) set(pixels, x, y); + } + } + + visible.textContent = render(pixels); } - }); + }; - qrImage.src = - "https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=" + - wallet.address; - donateTitle.textContent = "Donate " + wallet.name; - donateWarn.textContent = - "Send only " + - wallet.name + - " (" + - wallet.symbol + - ") to this deposit address. Sending any other coin or token to this address may result in the loss of your donation. Thanks!"; - walletAddress.value = wallet.address; - copyButton.textContent = "✚ Copy"; -} - -function copyText() { - var input = document.createElement("input"); - document.body.appendChild(input); - input.value = walletAddress.value; - input.select(); - document.execCommand("copy"); - document.body.removeChild(input); - copyButton.textContent = "✔ Copied"; -} - -cryptoWallets.forEach(function (wallet) { - var button = document.createElement("button"); - button.textContent = wallet.symbol; - button.addEventListener("click", function () { - selectWallet(wallet.symbol); - }); - walletsContainer.appendChild(button); -}); - -copyButton.addEventListener("click", copyText); - -selectWallet(cryptoWallets[0].symbol); - -// - -let globalUniforms = { - time: { value: 0 } -}; - -import * as THREE from "https://cdn.skypack.dev/three@0.136.0"; -import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls"; -import { - CSS2DRenderer, - CSS2DObject -} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/renderers/CSS2DRenderer.js"; - -let scene = new THREE.Scene(); -let camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 1, 2000); -camera.position.set(-5, 4, -0.8).setLength(14); -let renderer = new THREE.WebGLRenderer({ - antialias: true -}); -renderer.setSize(innerWidth, innerHeight); -renderer.setClearColor(0x241917); -document.body.appendChild(renderer.domElement); - -let labelRenderer = new CSS2DRenderer(); -labelRenderer.setSize(window.innerWidth, window.innerHeight); -labelRenderer.domElement.style.position = "absolute"; -labelRenderer.domElement.style.top = "0px"; -document.body.appendChild(labelRenderer.domElement); - -window.addEventListener("resize", onWindowResize); - -let controls = new OrbitControls(camera, labelRenderer.domElement); -controls.enablePan = false; -controls.minDistance = 10; -controls.maxDistance = 14; -controls.enableDamping = true; -controls.autoRotate = false; - -// - -let counter = 40000; -let rad = 5; -let sph = new THREE.Spherical(); - -let r = 0; -let dlong = Math.PI * (3 - Math.sqrt(5)); -let dz = 2 / counter; -let long = 0; -let z = 1 - dz / 2; - -let pts = []; -let clr = []; -let c = new THREE.Color(); -let uvs = []; - -for (let i = 0; i < counter; i++) { - r = Math.sqrt(1 - z * z); - let p = new THREE.Vector3( - Math.cos(long) * r, - z, - -Math.sin(long) * r - ).multiplyScalar(rad); - pts.push(p); - z = z - dz; - long = long + dlong; - - c.setHSL(0.45, 0.5, Math.random() * 0.25 + 0.25); - c.toArray(clr, i * 3); - - sph.setFromVector3(p); - uvs.push((sph.theta + Math.PI) / (Math.PI * 2), 1.0 - sph.phi / Math.PI); -} - -let g = new THREE.BufferGeometry().setFromPoints(pts); -g.setAttribute("color", new THREE.Float32BufferAttribute(clr, 3)); -g.setAttribute("uv", new THREE.Float32BufferAttribute(uvs, 2)); -let m = new THREE.PointsMaterial({ - size: 0.17, - vertexColors: false, - color: new THREE.Color(0x743c2f), - onBeforeCompile: (shader) => { - shader.uniforms.globeTexture = { - value: new THREE.TextureLoader().load(imgData) - }; - shader.vertexShader = ` - uniform sampler2D globeTexture; - varying float vVisibility; - varying vec3 vNormal; - varying vec3 vMvPosition; - ${shader.vertexShader} - `.replace( - `gl_PointSize = size;`, - ` - vVisibility = texture(globeTexture, uv).g; - gl_PointSize = size * (vVisibility < 0.5 ? 1. : 0.75); - vNormal = normalMatrix * normalize(position); - vMvPosition = -mvPosition.xyz; - gl_PointSize *= 0.4 + (dot(normalize(vMvPosition), vNormal) * 0.6); - ` - ); - shader.fragmentShader = ` - varying float vVisibility; - varying vec3 vNormal; - varying vec3 vMvPosition; - ${shader.fragmentShader} - `.replace( - `vec4 diffuseColor = vec4( diffuse, opacity );`, - ` - bool circ = length(gl_PointCoord - 0.5) > 0.5; - bool vis = dot(vMvPosition, vNormal) < 0.; - if (circ || vis) discard; - - vec3 col = diffuse + (vVisibility > 0.5 ? 0.5 : 0.); - - vec4 diffuseColor = vec4( col, opacity );` - ); - } -}); -let globe = new THREE.Points(g, m); -scene.add(globe); -// - -// - -let clock = new THREE.Clock(); - -renderer.setAnimationLoop(() => { - let t = clock.getElapsedTime(); - globalUniforms.time.value = t; - controls.update(); - renderer.render(scene, camera); - labelRenderer.render(scene, camera); -}); - -function onWindowResize() { - camera.aspect = innerWidth / innerHeight; - camera.updateProjectionMatrix(); - renderer.setSize(innerWidth, innerHeight); - labelRenderer.setSize(innerWidth, innerHeight); -} \ No newline at end of file + main(); +})(); diff --git a/public/style.css b/public/style.css index 6da4891..c7db824 100755 --- a/public/style.css +++ b/public/style.css @@ -1,322 +1,49 @@ +@import url("//cdn.jsdelivr.net/gh/be5invis/Iosevka@ff81c66/fonts.css"); + +:root { + --size: calc(100vmin / 1.618033988749895); +} + +html, body { - overflow: hidden; - margin: 0; - font-family: "Open Sans", sans-serif; -} - -.header-container { - color: white; - display: flex; - justify-content: space-between; - align-items: center; - position: fixed; - top: 1rem; - left: 1rem; - right: 1rem; - color: #fff; - z-index: 999; - background: rgba(255, 255, 255, 0.02); - backdrop-filter: blur(5px); - padding: 1rem; - padding-top: 0.5rem; - padding-bottom: 0.75rem; - border-radius: 1rem; -} - -.header-container h1 { - display: inline-block; - font-family: "Open Sans", sans-serif; - margin: 0; - padding: 0; -} - -.header-container nav ul { - list-style-type: none; - margin: 0; - padding: 0; -} - -.header-container nav ul li { - display: inline-block; - margin-left: 20px; -} - -.header-container nav ul li a { - text-decoration: none; - color: white; - font-weight: 800; - position: relative; -} - -.header-container nav ul li a::before { - content: ""; - position: absolute; width: 100%; - height: 2px; - bottom: 0; - left: 0; - background-color: white; - transform: scaleX(0); - transform-origin: bottom left; - transition: transform 0.3s ease; + height: 100vh; + overflow: hidden; } -.header-container nav ul li a:hover::before { - transform: scaleX(1); -} - -.card-button { - position: fixed; - z-index: 99; - right: 1.9rem; - bottom: 1.9rem; - padding: 5px 30px; - background-color: #232222; - color: #e3e3e3; - border-radius: 5px; - font-size: 22px; - font-weight: 800; - cursor: pointer; - transition: transform 0.3s; -} - -.card-button:hover { - animation: wobble 2s ease-in-out infinite; -} - -@keyframes wobble { - 0% { - transform: translateX(0); - } - 15% { - transform: translateX(-2px) rotate(-2deg); - } - 30% { - transform: translateX(2px) rotate(2deg); - } - 45% { - transform: translateX(-1px) rotate(-1deg); - } - 60% { - transform: translateX(1px) rotate(1deg); - } - 75% { - transform: translateX(-0.5px) rotate(-0.5deg); - } - 100% { - transform: translateX(0); - } -} - -.card-out { - z-index: 99; - position: fixed; - right: -520px; - bottom: 15px; - transition: right 0.5s ease-in-out; -} - -.card-in { - z-index: 99; - position: fixed; - right: 15px; - bottom: 15px; - transition: right 0.5s ease-in-out; -} - -*, -*:before, -*:after { - outline: 0; +body { margin: 0; - padding: 0; - border: 0; - text-decoration: none; - box-sizing: border-box; - transition: color 300ms ease-out, background 300ms ease-out, - border 300ms ease-out, transform 300ms ease-out, opacity 300ms ease-out; + background: #241917; + color: #f3bbae; } -input, -textarea, -select, -options, -button { - font-family: inherit; - font-size: inherit; - line-height: inherit; - font-weight: normal; - background: none; - color: #b4a477; -} - -.card-wrap { - overflow: hidden; - margin: 0 auto; - max-width: 520px; - background-color: #232323; - border-radius: 9px; - box-shadow: 7px 7px 0 #743c2f; -} - -.tabs-wrap { - position: relative; -} - -.tabs-nav { +body, +.braille { display: flex; - flex-direction: row; align-items: center; - justify-content: stretch; - position: relative; - overflow: hidden; - background-color: #232222; + justify-content: center; + flex-flow: row; } -.tabs-nav > button { - flex: 1; - display: block; - cursor: pointer; - text-align: center; - padding: 0.8em 0; - background-color: #232222; - font-weight: bold; - color: #733c2f; +.braille { + max-width: 100%; + max-height: 100%; + width: var(--size); + height: var(--size); + font: 11px/12px "Iosevka Web", monospace; } -.tabs-nav > button:hover { - background-color: #733c2f; - color: #232222; +.braille > * { + white-space: pre; } -.tabs-nav > button.active { - background-color: #733c2f; - border-color: #733c2f; - color: #232222; +.braille .hidden { + position: fixed; + bottom: 100%; + right: 100%; } -.tabs-info { - min-height: 100px; - padding-top: 1em; - background-color: #232222; - font-weight: 700; - color: #733c2f; +.visible { + display: fixed !important; + left: 2; } - -.tabs-info .tabs-info-row { - display: flex; - flex-direction: row; - align-items: center; - justify-content: stretch; - margin-bottom: 1em; - padding: 0 1em; -} - -.tabs-info .tabs-info-qr > img { - display: block; - border-radius: 10px; - background-color: white; - padding: 5px; -} - -.tabs-info .tabs-info-input { - display: flex; - flex-direction: row; - align-items: center; - justify-content: stretch; - background-color: #232323; - padding: 0.75em 1em; - box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.4); -} - -.tabs-info .tabs-info-input > span { - margin-right: 1em; - font-weight: bold; - color: #733c2f; -} - -.tabs-info .tabs-info-input > input { - flex: 1; - margin-right: 1em; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-weight: bold; - color: #733c2f; - background-color: #232323; - border: none; -} - -.tabs-info .tabs-info-input > button { - cursor: pointer; - font-weight: bold; - background-color: #232222; - color: #733c2f; -} - -.tabs-info .tabs-info-details { - padding-left: 15px; -} - -.tabs-info .tabs-info-title { - font-size: 2em; -} - -.tabs-info .tabs-info-warn { - font-size: 1em; -} - -.label-york, -.label-atl, -.label-cha, -.label-vint, -.label-san { - color: white; - background-color: rgba(0, 0, 0, 0.7); - padding: 4px; - border-radius: 4px; - font-size: 14px; - z-index: 99; -} - -.ping1, -.ping2, -.ping3{position:absolute;z-index:88;left:50%;top:50%;display:block;content:"";-webkit-border-radius:116px;-moz-border-radius:116px;border-radius:116px;border:2px solid #ee4633; - transition:all 0.2s ease-in-out; --webkit-transition:all 0.2s ease-in-out; - -moz-transition:all 0.2s ease-in-out; - -o-transition:all 0.2s ease-in-out; - width:0; - height:0; - margin-left:-2px; - margin-top:-2px;} - -.dot:hover .ping1, -.dot:hover .ping2, -.dot:hover .ping3 { - transition:all 0.75s ease-out; - -webkit-transition:all 0.75s ease-out; - -moz-transition:all 0.75s ease-out; - -o-transition:all 0.75s ease-out; -} -.dot:hover .ping1 { width:116px;height:116px; margin-left:-60px;margin-top:-60px; } -.dot:hover .ping2{width:66px;height:66px;margin-left:-35px;margin-top:-35px; - -moz-transition-delay:0.2s; - -webkit-transition-delay:0.2s; - -o-transition-delay:0.2s; - transition-delay:0.2s;} -.dot:hover .ping3{width:40px;height:40px;margin-left:-22px;margin-top:-22px; - -moz-transition-delay:0.5s; - -webkit-transition-delay:0.5s; - -o-transition-delay:0.5s; - transition-delay:0.5s;} - - -.dot{position:absolute;z-index:99;width:14px;height:14px;background:#ee4633;-webkit-border-radius:12px;-moz-border-radius:12px;border-radius:12px;cursor:pointer;} - -#map{position:relative;margin:5% auto;width:638px;} - -#portland{left:33px;top:50px;} -#palo_alto{left:17px;top:181px;} -#scottsdale {left:115px;top:246px;} -#san_antonio{left:296px;top:311px;}