diff --git a/js/artwork.js b/js/artwork.js new file mode 100644 index 0000000..3e6d7a9 --- /dev/null +++ b/js/artwork.js @@ -0,0 +1,169 @@ +"use strict"; + +function svgURI(svg) { + return "data:image/svg+xml," + encodeURIComponent(svg); +} + +function gid(seed, name) { + return "g" + name + seed; +} + +function artSVG(palette, seed, pattern) { + const rnd = seeded(seed); + const c1 = palette[0], c2 = palette[1], c3 = palette[2]; + const id = gid(seed, pattern); + let inner = ""; + + if (pattern === "mesh") { + inner = ` + + + + + + + + + + + + + + + + `; + } + + if (pattern === "waves") { + let bands = ""; + for (let i = 0; i < 6; i++) { + const y = 60 + i * 78 + rnd() * 24; + const amp = 26 + rnd() * 30; + const col = [c1, c2, c3, "#ffffff"][i % 4]; + const op = 0.75 - i * 0.09; + bands += ``; + } + inner = `${bands}`; + } + + if (pattern === "arcs") { + let arcs = ""; + const cx = 120 + rnd() * 200, cy = 120 + rnd() * 200; + for (let i = 0; i < 9; i++) { + const r = 40 + i * 42 + rnd() * 20; + const col = [c1, c2, c3, "#ffffff"][i % 4]; + arcs += ``; + } + inner = ` + + + ${arcs}`; + } + + if (pattern === "rings") { + let rings = ""; + for (let i = 0; i < 7; i++) { + const r = 60 + i * 55; + const col = [c1, c2, c3, "#ffffff"][i % 4]; + rings += ``; + } + inner = ` + + + ${rings}`; + } + + if (pattern === "stripes") { + inner = ` + + + + ${[0, 1, 2, 3, 4, 5, 6].map((i) => ``).join("")} + ${[0, 1, 2, 3].map((i) => ``).join("")} + `; + } + + if (pattern === "sparkle") { + let dots = ""; + for (let x = 20; x < 512; x += 26) { + for (let y = 20; y < 512; y += 26) { + const r = rnd(); + if (r < 0.28) continue; + const size = 1 + rnd() * 5; + const col = [c1, c2, c3, "#ffffff"][Math.floor(rnd() * 4)]; + dots += ``; + } + } + inner = ` + + + ${dots}`; + } + + if (pattern === "orbital") { + let stars = ""; + for (let i = 0; i < 70; i++) { + stars += ``; + } + inner = ` + ${stars} + + + + + + + + + `; + } + + if (pattern === "grain") { + let grains = ""; + for (let i = 0; i < 260; i++) { + grains += ``; + } + inner = ` + + + ${grains} + `; + } + + return `${inner}`; +} + +const Art = { + album(album) { + const pattern = ["mesh", "waves", "arcs", "rings", "stripes", "sparkle", "orbital", "grain"][album.seed % 8]; + return svgURI(artSVG(album.palette, album.seed, pattern)); + }, + song(song) { + return Art.album(D.album(song.albumId)); + }, + mix(mix) { + return svgURI(artSVG(mix.palette, hashStr(mix.id) % 997, ["mesh", "orbital", "sparkle", "rings"][hashStr(mix.id) % 4])); + }, + station(station) { + return svgURI(artSVG(station.palette, station.seed * 7 + 1, ["arcs", "sparkle", "waves", "stripes"][station.seed % 4])); + }, + artist(artist) { + const initials = artist.name.split(" ").map((w) => w[0]).slice(0, 2).join("").toUpperCase(); + const rnd = seeded(hashStr(artist.id)); + const r1 = 30 + rnd() * 200, r2 = 30 + rnd() * 200; + const svg = ` + + + + + + + + ${initials} + `; + return svgURI(svg); + }, + placeholder() { + return svgURI(``); + } +};