primo commit
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
/* Utility condivise tra le pagine (galassia e classifiche) */
|
||||
"use strict";
|
||||
|
||||
/* ---------------- utility base ---------------- */
|
||||
function esc(s) {
|
||||
return String(s ?? "").replace(/[&<>"']/g, (c) =>
|
||||
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c]));
|
||||
}
|
||||
function num(v) { return (v === null || v === undefined) ? "—" : Number(v).toLocaleString("it"); }
|
||||
function hashStr(s) { let h = 0; for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0; return Math.abs(h); }
|
||||
|
||||
async function api(path, opts) {
|
||||
const r = await fetch(path, opts);
|
||||
let data = null;
|
||||
try { data = await r.json(); } catch (_) { /* noop */ }
|
||||
if (!r.ok) throw new Error((data && data.error) || ("Errore HTTP " + r.status));
|
||||
return data;
|
||||
}
|
||||
|
||||
/* ---------------- icone SVG (window.ICONS da icons.js) ---------------- */
|
||||
function icon(name, size = 16) {
|
||||
const it = (window.ICONS || {})[name];
|
||||
if (!it) return "";
|
||||
return `<svg class="ic" width="${size}" height="${size}" viewBox="${it.vb}" ` +
|
||||
`xmlns="http://www.w3.org/2000/svg" aria-hidden="true">${it.body}</svg>`;
|
||||
}
|
||||
|
||||
/* ---------------- avatar pianeti/lune (SVG) ---------------- */
|
||||
let _svgSeq = 0;
|
||||
const PLANET_PAL = [
|
||||
["#ffd9a0", "#e0762c"], ["#f2b3a0", "#b3422f"], ["#ffb1c0", "#a0275a"],
|
||||
["#9fd8ff", "#2a6fc4"], ["#8fe8c0", "#1e7a5f"], ["#d3b8ff", "#6d3fc4"],
|
||||
["#f5e3a0", "#c2a22e"], ["#c3d0e2", "#5c6f8c"],
|
||||
];
|
||||
const LUNA_PAL = [["#e6e6e6", "#9a9a9a"]];
|
||||
|
||||
function artSVG(seedKey, size, moon = false) {
|
||||
const seed = hashStr(seedKey) || 1;
|
||||
const r = 15; // viewBox 32
|
||||
const pal = (moon ? LUNA_PAL : PLANET_PAL)[seed % (moon ? 1 : PLANET_PAL.length)];
|
||||
const id = "g" + (++_svgSeq);
|
||||
let extras = "";
|
||||
if (moon) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const cx = 7 + ((seed >> (i * 3)) % 18);
|
||||
const cy = 7 + ((seed >> (i * 5 + 2)) % 18);
|
||||
const cr = 2 + ((seed >> (i * 2 + 1)) % 3);
|
||||
extras += `<circle cx="${cx}" cy="${cy}" r="${cr}" fill="rgba(0,0,0,.18)"/>` +
|
||||
`<circle cx="${cx}" cy="${cy}" r="${cr}" fill="none" stroke="rgba(255,255,255,.28)" stroke-width=".7"/>`;
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const cx = 8 + ((seed >> (i * 4)) % 14);
|
||||
const cy = 6 + ((seed >> (i * 3 + 1)) % 14);
|
||||
extras += `<circle cx="${cx}" cy="${cy}" r="${5 + ((seed >> i) % 5)}" fill="rgba(255,255,255,.10)"/>`;
|
||||
}
|
||||
}
|
||||
return `<svg width="${size}" height="${size}" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">` +
|
||||
`<defs><radialGradient id="${id}" cx=".35" cy=".3" r=".95">` +
|
||||
`<stop offset="0" stop-color="${pal[0]}"/><stop offset="1" stop-color="${pal[1]}"/>` +
|
||||
`</radialGradient></defs>` +
|
||||
`<circle cx="16" cy="16" r="${r}" fill="url(#${id})"/>` +
|
||||
extras +
|
||||
`<path d="M2 17a14 14 0 0 0 28 0 12 9 0 0 1 -28 0z" fill="rgba(0,0,0,.30)"/>` +
|
||||
`<circle cx="16" cy="16" r="${r}" fill="none" stroke="rgba(0,0,0,.35)" stroke-width="1"/>` +
|
||||
`</svg>`;
|
||||
}
|
||||
|
||||
/* ---------------- sfondo stellare ---------------- */
|
||||
function initStars() {
|
||||
const cv = document.getElementById("space");
|
||||
if (!cv) return;
|
||||
let ctx = null;
|
||||
try { ctx = cv.getContext("2d"); } catch (_) { /* noop */ }
|
||||
if (!ctx) return; // mai bloccare il resto dell'app
|
||||
let stars = [], tw = [];
|
||||
function resize() {
|
||||
cv.width = innerWidth; cv.height = innerHeight;
|
||||
stars = []; tw = [];
|
||||
const n = Math.floor((cv.width * cv.height) / 6500);
|
||||
for (let i = 0; i < n; i++) {
|
||||
stars.push({ x: Math.random() * cv.width, y: Math.random() * cv.height,
|
||||
r: Math.random() * 1.1 + .25, a: Math.random() * .5 + .2 });
|
||||
}
|
||||
for (let i = 0; i < 26; i++) {
|
||||
tw.push({ x: Math.random() * cv.width, y: Math.random() * cv.height,
|
||||
r: Math.random() * 1.2 + .4, p: Math.random() * Math.PI * 2, s: .8 + Math.random() });
|
||||
}
|
||||
}
|
||||
resize();
|
||||
addEventListener("resize", resize);
|
||||
(function draw(t) {
|
||||
ctx.clearRect(0, 0, cv.width, cv.height);
|
||||
for (const s of stars) {
|
||||
ctx.globalAlpha = s.a; ctx.fillStyle = "#cfe0ff";
|
||||
ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, 7); ctx.fill();
|
||||
}
|
||||
const k = t / 1000;
|
||||
for (const s of tw) {
|
||||
ctx.globalAlpha = .25 + .6 * Math.abs(Math.sin(k * s.s + s.p));
|
||||
ctx.fillStyle = "#fff";
|
||||
ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, 7); ctx.fill();
|
||||
}
|
||||
ctx.globalAlpha = 1;
|
||||
requestAnimationFrame(draw);
|
||||
})(performance.now());
|
||||
}
|
||||
Reference in New Issue
Block a user