| 1 | /*! Fiesta 1.2.0 | MPL-2.0 | https://fiesta.rastrillo.org */ |
| 2 | (function () { |
| 3 | "use strict"; |
| 4 | var root = document.documentElement; |
| 5 | if (!window.matchMedia || !window.matchMedia("all").addEventListener) return; |
| 6 | var reduce = matchMedia("(prefers-reduced-motion: reduce)"); |
| 7 | var forced = matchMedia("(forced-colors: active)"); |
| 8 | |
| 9 | var FOLLOW = false; |
| 10 | var WRITE_MS = 200; |
| 11 | var BTN = "[rst-btn],.rst-btn"; |
| 12 | var CARD = "[rst-box],.rst-box,[rst-card],.rst-card,[rst-stats],.rst-stats,[rst-list],.rst-list"; |
| 13 | var LIGHT_T = 125, CARD_T = 320, LIT_T = 400; |
| 14 | |
| 15 | var on = false, tx = 0, ty = -1, lx = 0, ly = -1, wx = 0, wy = -1; |
| 16 | var raf = 0, last = 0, pending = null, pointer = false, hold = false, force = false, wrote = 0; |
| 17 | var cards = new WeakMap(), live = new Set(), timers = new Set(), clock = 0; |
| 18 | |
| 19 | function sun() { |
| 20 | var d = new Date(), h = d.getHours() + d.getMinutes() / 60; |
| 21 | var t = Math.max(-1, Math.min(1, (h - 12) / 6)); |
| 22 | return [t * 0.8, -1 + Math.abs(t) * 0.35]; |
| 23 | } |
| 24 | function target() { |
| 25 | if (hold || (pointer && FOLLOW)) return; |
| 26 | var s = sun(); |
| 27 | tx = s[0]; |
| 28 | ty = s[1]; |
| 29 | } |
| 30 | function go() { |
| 31 | if (!on || document.hidden) return; |
| 32 | if (!raf) raf = requestAnimationFrame(step); |
| 33 | } |
| 34 | function ease(v, to, dt, T) { |
| 35 | return v + (to - v) * (1 - Math.exp(-dt / T)); |
| 36 | } |
| 37 | function light(el, x, y) { |
| 38 | var o = cards.get(el); |
| 39 | if (!o) { o = { x: x, y: y, l: 0 }; cards.set(el, o); } |
| 40 | o.tx = x; o.ty = y; o.tl = 1; |
| 41 | live.add(el); |
| 42 | } |
| 43 | function dim(el) { |
| 44 | var o = cards.get(el); |
| 45 | if (o) { o.tl = 0; live.add(el); } |
| 46 | } |
| 47 | |
| 48 | function step(now) { |
| 49 | raf = 0; |
| 50 | var dt = last ? Math.min(100, now - last) : 16; |
| 51 | last = now; |
| 52 | var moving = false; |
| 53 | if (pending) { |
| 54 | var e = pending; |
| 55 | pending = null; |
| 56 | var b = e.target.closest && e.target.closest(BTN); |
| 57 | var c = e.target.closest && e.target.closest(CARD); |
| 58 | var br = b && b.getBoundingClientRect(); |
| 59 | var cr = c && c.getBoundingClientRect(); |
| 60 | if (b) { |
| 61 | b.style.setProperty("--rst-mx", (e.clientX - br.left).toFixed(0) + "px"); |
| 62 | b.style.setProperty("--rst-my", (e.clientY - br.top).toFixed(0) + "px"); |
| 63 | } |
| 64 | live.forEach(function (k) { if (k !== c) dim(k); }); |
| 65 | if (c) light(c, e.clientX - cr.left, e.clientY - cr.top); |
| 66 | } |
| 67 | if (!hold) { |
| 68 | lx = ease(lx, tx, dt, LIGHT_T); |
| 69 | ly = ease(ly, ty, dt, LIGHT_T); |
| 70 | } |
| 71 | if (force || ((Math.abs(lx - wx) > 0.01 || Math.abs(ly - wy) > 0.01) && now - wrote >= WRITE_MS)) { |
| 72 | force = false; |
| 73 | wx = lx; wy = ly; wrote = now; |
| 74 | root.style.setProperty("--rst-light-x", lx.toFixed(3)); |
| 75 | root.style.setProperty("--rst-light-y", ly.toFixed(3)); |
| 76 | } |
| 77 | if (Math.abs(tx - lx) > 0.002 || Math.abs(ty - ly) > 0.002) moving = true; |
| 78 | live.forEach(function (el) { |
| 79 | if (!el.isConnected) { live.delete(el); return; } |
| 80 | var o = cards.get(el); |
| 81 | o.x = ease(o.x, o.tx, dt, CARD_T); |
| 82 | o.y = ease(o.y, o.ty, dt, CARD_T); |
| 83 | o.l = ease(o.l, o.tl, dt, LIT_T); |
| 84 | var done = Math.abs(o.tx - o.x) < 0.5 && Math.abs(o.ty - o.y) < 0.5 && Math.abs(o.tl - o.l) < 0.004; |
| 85 | if (done) { o.x = o.tx; o.y = o.ty; o.l = o.tl; } |
| 86 | if (!done || !o.still) { |
| 87 | el.style.setProperty("--rst-card-x", o.x.toFixed(1) + "px"); |
| 88 | el.style.setProperty("--rst-card-y", o.y.toFixed(1) + "px"); |
| 89 | el.style.setProperty("--rst-card-lit", o.l.toFixed(3)); |
| 90 | } |
| 91 | o.still = done; |
| 92 | if (!done) moving = true; else if (o.tl === 0) live.delete(el); |
| 93 | }); |
| 94 | if (moving) go(); else last = 0; |
| 95 | } |
| 96 | |
| 97 | function onMove(e) { |
| 98 | if (e.pointerType !== "mouse") return; |
| 99 | if (FOLLOW && !hold) { |
| 100 | pointer = true; |
| 101 | tx = Math.max(-1, Math.min(1, (e.clientX / innerWidth - 0.5) * 2)); |
| 102 | ty = Math.max(-1, Math.min(1, (e.clientY / innerHeight - 0.5) * 2)) * 0.6 - 0.4; |
| 103 | } |
| 104 | pending = e; |
| 105 | go(); |
| 106 | } |
| 107 | function onDown(e) { |
| 108 | var b = e.target.closest && e.target.closest(BTN); |
| 109 | var c = e.pointerType !== "mouse" && e.target.closest && e.target.closest(CARD); |
| 110 | var br = b && b.getBoundingClientRect(); |
| 111 | var cr = c && c.getBoundingClientRect(); |
| 112 | if (b) { |
| 113 | b.style.setProperty("--rst-px", (e.clientX - br.left).toFixed(0) + "px"); |
| 114 | b.style.setProperty("--rst-py", (e.clientY - br.top).toFixed(0) + "px"); |
| 115 | } |
| 116 | if (e.pointerType === "mouse") return; |
| 117 | leavePointer(); |
| 118 | if (c) { |
| 119 | light(c, e.clientX - cr.left, e.clientY - cr.top); |
| 120 | var id = setTimeout(function () { timers.delete(id); dim(c); go(); }, 1400); |
| 121 | timers.add(id); |
| 122 | go(); |
| 123 | } |
| 124 | } |
| 125 | function leavePointer() { |
| 126 | pointer = false; |
| 127 | target(); |
| 128 | go(); |
| 129 | } |
| 130 | function onLeave() { |
| 131 | pending = null; |
| 132 | live.forEach(dim); |
| 133 | leavePointer(); |
| 134 | } |
| 135 | function onVisibility() { |
| 136 | if (document.hidden) { |
| 137 | if (raf) cancelAnimationFrame(raf); |
| 138 | raf = 0; last = 0; |
| 139 | } else { |
| 140 | go(); |
| 141 | } |
| 142 | } |
| 143 | function onHook(e) { |
| 144 | var d = e.detail || {}; |
| 145 | hold = !!d.hold; |
| 146 | if (typeof d.x === "number") { tx = lx = d.x; } |
| 147 | if (typeof d.y === "number") { ty = ly = d.y; } |
| 148 | force = true; |
| 149 | go(); |
| 150 | } |
| 151 | |
| 152 | function start() { |
| 153 | if (on) return; |
| 154 | on = true; |
| 155 | addEventListener("pointermove", onMove, { passive: true }); |
| 156 | addEventListener("pointerdown", onDown, { passive: true }); |
| 157 | addEventListener("keydown", leavePointer, { passive: true }); |
| 158 | document.addEventListener("pointerleave", onLeave); |
| 159 | document.addEventListener("visibilitychange", onVisibility); |
| 160 | document.addEventListener("rst:light", onHook); |
| 161 | clock = setInterval(function () { target(); go(); }, 5 * 60 * 1000); |
| 162 | target(); |
| 163 | lx = tx; ly = ty; force = true; |
| 164 | go(); |
| 165 | } |
| 166 | function stop() { |
| 167 | if (!on) return; |
| 168 | on = false; |
| 169 | removeEventListener("pointermove", onMove); |
| 170 | removeEventListener("pointerdown", onDown); |
| 171 | removeEventListener("keydown", leavePointer); |
| 172 | document.removeEventListener("pointerleave", onLeave); |
| 173 | document.removeEventListener("visibilitychange", onVisibility); |
| 174 | document.removeEventListener("rst:light", onHook); |
| 175 | clearInterval(clock); |
| 176 | timers.forEach(clearTimeout); |
| 177 | timers.clear(); |
| 178 | if (raf) cancelAnimationFrame(raf); |
| 179 | raf = 0; last = 0; pending = null; pointer = false; hold = false; force = false; wrote = 0; |
| 180 | lx = wx = tx = 0; ly = wy = ty = -1; |
| 181 | live.clear(); |
| 182 | cards = new WeakMap(); |
| 183 | root.style.removeProperty("--rst-light-x"); |
| 184 | root.style.removeProperty("--rst-light-y"); |
| 185 | var written = document.querySelectorAll('[style*="--rst-"]'); |
| 186 | for (var i = 0; i < written.length; i++) { |
| 187 | ["--rst-mx", "--rst-my", "--rst-px", "--rst-py", "--rst-card-x", "--rst-card-y", "--rst-card-lit"].forEach(function (p) { |
| 188 | written[i].style.removeProperty(p); |
| 189 | }); |
| 190 | } |
| 191 | } |
| 192 | function settle() { |
| 193 | if (reduce.matches || forced.matches) stop(); else start(); |
| 194 | } |
| 195 | reduce.addEventListener("change", settle); |
| 196 | forced.addEventListener("change", settle); |
| 197 | settle(); |
| 198 | })(); |
| 199 | |