music video renderer web app deftoku.digi.rip
audio visualizer webapp
1

Configure Feed

Select the types of activity you want to include in your feed.

cd-top: add image options

digi.rip (Jun 22, 2026, 12:55 AM EDT) 9915d625 1e7585b6

+46 -4
+15
src/ui/params.ts
··· 75 75 }); 76 76 container.appendChild(label); 77 77 container.appendChild(input); 78 + } else if (p.type === "select") { 79 + const select = document.createElement("select"); 80 + select.id = `param-${p.key}`; 81 + for (const v of p.values ?? []) { 82 + const opt = document.createElement("option"); 83 + opt.value = v; 84 + opt.textContent = v; 85 + if (v === String(p.default)) opt.selected = true; 86 + select.appendChild(opt); 87 + } 88 + select.addEventListener("change", () => { 89 + cachedOpts[p.key] = select.value; 90 + }); 91 + container.appendChild(label); 92 + container.appendChild(select); 78 93 } else if (p.type === "text") { 79 94 const input = document.createElement("input"); 80 95 input.type = "text";
+1
src/visualizers/index.ts
··· 50 50 min?: number; 51 51 max?: number; 52 52 step?: number; 53 + values?: string[]; 53 54 label: string; 54 55 inputStyle?: Partial<CSSStyleDeclaration>; 55 56 }>;
+30 -4
src/visualizers/media/cd-top.ts
··· 18 18 label: "label img", 19 19 }, 20 20 { 21 + key: "labelFit", 22 + type: "select", 23 + default: "fill", 24 + values: ["fill", "fit", "stretch"], 25 + label: "fit", 26 + }, 27 + { 21 28 key: "bgImg", 22 29 type: "img", 23 30 default: "", ··· 227 234 ctx.save(); 228 235 filledRing(ctx, outerRadius, hubInnerRadius, ""); 229 236 ctx.clip(); 230 - const imgScale = (outerRadius * 2) / labelImg.naturalWidth; 231 - const iw = outerRadius * 2; 232 - const ih = labelImg.naturalHeight * imgScale; 233 - ctx.drawImage(labelImg, -outerRadius, -ih / 2, iw, ih); 237 + const discSize = outerRadius * 2; 238 + const labelFit = (options["labelFit"] as string) || "fill"; 239 + let iw: number, ih: number; 240 + if (labelFit === "fit") { 241 + const scale = Math.min( 242 + discSize / labelImg.naturalWidth, 243 + discSize / labelImg.naturalHeight, 244 + ); 245 + iw = labelImg.naturalWidth * scale; 246 + ih = labelImg.naturalHeight * scale; 247 + } else if (labelFit === "stretch") { 248 + iw = discSize; 249 + ih = discSize; 250 + } else { 251 + // fill (cover) 252 + const scale = Math.max( 253 + discSize / labelImg.naturalWidth, 254 + discSize / labelImg.naturalHeight, 255 + ); 256 + iw = labelImg.naturalWidth * scale; 257 + ih = labelImg.naturalHeight * scale; 258 + } 259 + ctx.drawImage(labelImg, -iw / 2, -ih / 2, iw, ih); 234 260 ctx.restore(); 235 261 } 236 262