This repository has been archived on 2025-08-23. You can view files and clone it, but cannot push or open issues or pull requests.
Files
GreenCoast/client/avatar.js

45 lines
1.6 KiB
JavaScript

// Deterministic, local-only avatars. No network calls.
export function avatarDataURL(seed, size = 40) {
// Hash seed → bytes
const h = sha256(seed);
// Colors from bytes
const hue = h[0] % 360;
const bg = `hsl(${(h[1]*3)%360} 25% 14%)`;
const fg = `hsl(${hue} 70% 60%)`;
// 5x5 grid mirrored; draw squares where bits set
const cells = 5, scale = Math.floor(size / cells);
let rects = "";
for (let y = 0; y < cells; y++) {
for (let x = 0; x < Math.ceil(cells/2); x++) {
const bit = (h[(y*3 + x) % h.length] >> (y % 5)) & 1;
if (bit) {
const xL = x*scale, xR = (cells-1-x)*scale, yP = y*scale;
rects += `<rect x="${xL}" y="${yP}" width="${scale}" height="${scale}" rx="2" ry="2" fill="${fg}"/>`;
if (x !== cells-1-x) {
rects += `<rect x="${xR}" y="${yP}" width="${scale}" height="${scale}" rx="2" ry="2" fill="${fg}"/>`;
}
}
}
}
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${cells*scale} ${cells*scale}">
<rect width="100%" height="100%" fill="${bg}"/>${rects}
</svg>`;
return "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svg)));
}
function sha256(s) {
// Simple synchronous hash-ish bytes from string (non-cryptographic; fine for visuals)
let h1 = 0x6a09e667, h2 = 0xbb67ae85;
for (let i=0;i<s.length;i++) {
const c = s.charCodeAt(i);
h1 = (h1 ^ c) * 0x45d9f3b + ((h1<<7) | (h1>>>25));
h2 = (h2 ^ (c<<1)) * 0x27d4eb2d + ((h2<<9) | (h2>>>23));
}
const out = new Uint8Array(32);
for (let i=0;i<32;i++){
out[i] = (h1 >> (i%24)) ^ (h2 >> ((i*3)%24)) ^ (i*31);
}
return out;
}