mirror of
https://github.com/planetrenox/logo.git
synced 2026-10-29 11:44:52 +00:00
Move renox-as-planet into self-contained versions/blue
Each design version now carries its own package.json, lockfile, script, README and rendered files, so versions can be built and changed independently. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# Renox as a planet: blue
|
||||
|
||||

|
||||
|
||||
The word **Renox** is the planet. The script uses [opentype.js](https://github.com/opentypejs/opentype.js) to turn the word, set in Unbounded Black, into vector outlines, and splits every curve into many short segments. It then wraps each point around a 3D sphere with an orthographic projection. That way the letters curve over the globe and get squeezed toward its edges like real continents. Stacked shells raise the letters off the surface, and gradients light the whole planet from one light source. Clouds, an ice cap, an atmosphere glow, a few islands, a ring and a moon finish it off. [resvg](https://github.com/thx/resvg-js) renders the PNGs.
|
||||
|
||||
```sh
|
||||
bun install
|
||||
bun run build
|
||||
```
|
||||
|
||||
| file | what |
|
||||
| --- | --- |
|
||||
| `logo.svg` / `logo.png` | on a deep-space background |
|
||||
| `logo-transparent.svg` / `logo-transparent.png` | planet only, transparent background |
|
||||
|
||||
The settings at the top of `index.js` control the camera tilt (`T`), how far the word wraps around the planet (`SPAN`), how high the letters rise (`RISE`), the letter spacing (`TRACK`), the light direction (`L`) and the ring bands (`RINGS`).
|
||||
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"lockfileVersion": 2,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "logo",
|
||||
"dependencies": {
|
||||
"@fontsource/unbounded": "^5.3.0",
|
||||
"@resvg/resvg-js": "^2.6.2",
|
||||
"opentype.js": "^2.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@fontsource/unbounded": ["@fontsource/unbounded@5.3.0", "", {}, "sha512-pPD6hsTnjoQRr6pCsqMHbHBfauB4LZygCNQEUJHu+CO2wzDFHqELEFSG7sTwo5Z5Gr4q3OK0fIILOXBJDv6lcw=="],
|
||||
|
||||
"@resvg/resvg-js": ["@resvg/resvg-js@2.6.2", "", { "optionalDependencies": { "@resvg/resvg-js-android-arm-eabi": "2.6.2", "@resvg/resvg-js-android-arm64": "2.6.2", "@resvg/resvg-js-darwin-arm64": "2.6.2", "@resvg/resvg-js-darwin-x64": "2.6.2", "@resvg/resvg-js-linux-arm-gnueabihf": "2.6.2", "@resvg/resvg-js-linux-arm64-gnu": "2.6.2", "@resvg/resvg-js-linux-arm64-musl": "2.6.2", "@resvg/resvg-js-linux-x64-gnu": "2.6.2", "@resvg/resvg-js-linux-x64-musl": "2.6.2", "@resvg/resvg-js-win32-arm64-msvc": "2.6.2", "@resvg/resvg-js-win32-ia32-msvc": "2.6.2", "@resvg/resvg-js-win32-x64-msvc": "2.6.2" } }, "sha512-xBaJish5OeGmniDj9cW5PRa/PtmuVU3ziqrbr5xJj901ZDN4TosrVaNZpEiLZAxdfnhAe7uQ7QFWfjPe9d9K2Q=="],
|
||||
|
||||
"@resvg/resvg-js-android-arm-eabi": ["@resvg/resvg-js-android-arm-eabi@2.6.2", "", { "os": "android", "cpu": "arm" }, "sha512-FrJibrAk6v29eabIPgcTUMPXiEz8ssrAk7TXxsiZzww9UTQ1Z5KAbFJs+Z0Ez+VZTYgnE5IQJqBcoSiMebtPHA=="],
|
||||
|
||||
"@resvg/resvg-js-android-arm64": ["@resvg/resvg-js-android-arm64@2.6.2", "", { "os": "android", "cpu": "arm64" }, "sha512-VcOKezEhm2VqzXpcIJoITuvUS/fcjIw5NA/w3tjzWyzmvoCdd+QXIqy3FBGulWdClvp4g+IfUemigrkLThSjAQ=="],
|
||||
|
||||
"@resvg/resvg-js-darwin-arm64": ["@resvg/resvg-js-darwin-arm64@2.6.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-nmok2LnAd6nLUKI16aEB9ydMC6Lidiiq2m1nEBDR1LaaP7FGs4AJ90qDraxX+CWlVuRlvNjyYJTNv8qFjtL9+A=="],
|
||||
|
||||
"@resvg/resvg-js-darwin-x64": ["@resvg/resvg-js-darwin-x64@2.6.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-GInyZLjgWDfsVT6+SHxQVRwNzV0AuA1uqGsOAW+0th56J7Nh6bHHKXHBWzUrihxMetcFDmQMAX1tZ1fZDYSRsw=="],
|
||||
|
||||
"@resvg/resvg-js-linux-arm-gnueabihf": ["@resvg/resvg-js-linux-arm-gnueabihf@2.6.2", "", { "os": "linux", "cpu": "arm" }, "sha512-YIV3u/R9zJbpqTTNwTZM5/ocWetDKGsro0SWp70eGEM9eV2MerWyBRZnQIgzU3YBnSBQ1RcxRZvY/UxwESfZIw=="],
|
||||
|
||||
"@resvg/resvg-js-linux-arm64-gnu": ["@resvg/resvg-js-linux-arm64-gnu@2.6.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zc2BlJSim7YR4FZDQ8OUoJg5holYzdiYMeobb9pJuGDidGL9KZUv7SbiD4E8oZogtYY42UZEap7dqkkYuA91pg=="],
|
||||
|
||||
"@resvg/resvg-js-linux-arm64-musl": ["@resvg/resvg-js-linux-arm64-musl@2.6.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-3h3dLPWNgSsD4lQBJPb4f+kvdOSJHa5PjTYVsWHxLUzH4IFTJUAnmuWpw4KqyQ3NA5QCyhw4TWgxk3jRkQxEKg=="],
|
||||
|
||||
"@resvg/resvg-js-linux-x64-gnu": ["@resvg/resvg-js-linux-x64-gnu@2.6.2", "", { "os": "linux", "cpu": "x64" }, "sha512-IVUe+ckIerA7xMZ50duAZzwf1U7khQe2E0QpUxu5MBJNao5RqC0zwV/Zm965vw6D3gGFUl7j4m+oJjubBVoftw=="],
|
||||
|
||||
"@resvg/resvg-js-linux-x64-musl": ["@resvg/resvg-js-linux-x64-musl@2.6.2", "", { "os": "linux", "cpu": "x64" }, "sha512-UOf83vqTzoYQO9SZ0fPl2ZIFtNIz/Rr/y+7X8XRX1ZnBYsQ/tTb+cj9TE+KHOdmlTFBxhYzVkP2lRByCzqi4jQ=="],
|
||||
|
||||
"@resvg/resvg-js-win32-arm64-msvc": ["@resvg/resvg-js-win32-arm64-msvc@2.6.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-7C/RSgCa+7vqZ7qAbItfiaAWhyRSoD4l4BQAbVDqRRsRgY+S+hgS3in0Rxr7IorKUpGE69X48q6/nOAuTJQxeQ=="],
|
||||
|
||||
"@resvg/resvg-js-win32-ia32-msvc": ["@resvg/resvg-js-win32-ia32-msvc@2.6.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-har4aPAlvjnLcil40AC77YDIk6loMawuJwFINEM7n0pZviwMkMvjb2W5ZirsNOZY4aDbo5tLx0wNMREp5Brk+w=="],
|
||||
|
||||
"@resvg/resvg-js-win32-x64-msvc": ["@resvg/resvg-js-win32-x64-msvc@2.6.2", "", { "os": "win32", "cpu": "x64" }, "sha512-ZXtYhtUr5SSaBrUDq7DiyjOFJqBVL/dOBN7N/qmi/pO0IgiWW/f/ue3nbvu9joWE5aAKDoIzy/CxsY0suwGosQ=="],
|
||||
|
||||
"opentype.js": ["opentype.js@2.0.0", "", { "bin": { "ot": "bin/ot" } }, "sha512-kCyjv6xdDY1W/jLWZ/L3QhhTlKUqDZMQ5+Jdlw12b3dXkKNpYBqqlMMj0YDQPShWFTMwgZI1hG14kN3XUDSg/A=="],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// Renox as a planet: the word's glyph outlines are wrapped onto a sphere as raised
|
||||
// continents, then lit, given an atmosphere, clouds, an ice cap and a ring.
|
||||
import opentype from 'opentype.js'
|
||||
import { Resvg } from '@resvg/resvg-js'
|
||||
import { readFileSync, writeFileSync } from 'fs'
|
||||
|
||||
const at = p => new URL(p, import.meta.url)
|
||||
const fb = readFileSync(at('node_modules/@fontsource/unbounded/files/unbounded-latin-900-normal.woff'))
|
||||
const font = opentype.parse(fb.buffer.slice(fb.byteOffset, fb.byteOffset + fb.byteLength))
|
||||
|
||||
const { sin, cos, hypot, ceil, min, max, PI } = Math
|
||||
const D = PI / 180, S = 1200, C = S / 2, R = 300
|
||||
const T = 18 * D // camera elevation above the equator
|
||||
const SPAN = 66 * D // half the longitude the word wraps around
|
||||
const LAT = T // word latitude, puts it dead centre of the disc
|
||||
const RISE = .03 // continent height as a fraction of R
|
||||
const TRACK = 4 // letter spacing in em/100
|
||||
const L = (v => v.map(c => c / hypot(...v)))([-.55, .62, .56]) // light, view space
|
||||
const RINGS = [[1.3, 1.37, .25], [1.39, 1.58, .7], [1.61, 1.64, .3], [1.67, 1.8, .5], [1.82, 1.85, .22]]
|
||||
const n = v => +v.toFixed(1)
|
||||
const rnd = (s => () => (s = (s * 16807) % 2147483647) / 2147483647)(7)
|
||||
|
||||
// lon/lat on a sphere of radius r -> screen [x, y, depth] (depth > 0 faces the camera)
|
||||
const P = (lon, lat, r = 1) => {
|
||||
const x = cos(lat) * sin(lon), y = sin(lat), z = cos(lat) * cos(lon)
|
||||
return [C + R * r * x, C - R * r * (y * cos(T) - z * sin(T)), y * sin(T) + z * cos(T)]
|
||||
}
|
||||
const poly = pts => 'M' + pts.map(([x, y]) => n(x) + ' ' + n(y)).join('L')
|
||||
|
||||
// lay out the word, then flatten every outline into dense polylines so straight
|
||||
// strokes bend properly once they are wrapped round the sphere
|
||||
const cmds = []
|
||||
const gs = font.stringToGlyphs('RENOX')
|
||||
gs.reduce((x, g, i) => {
|
||||
cmds.push(...g.getPath(x, 0, 100).commands)
|
||||
return x + (g.advanceWidth + (gs[i + 1] ? font.getKerningValue(g, gs[i + 1]) : 0)) / font.unitsPerEm * 100 + TRACK
|
||||
}, 0)
|
||||
const bez = (q, t) => q.length < 2 ? q[0] : bez(q.slice(1).map((v, i) => [q[i][0] + (v[0] - q[i][0]) * t, q[i][1] + (v[1] - q[i][1]) * t]), t)
|
||||
const outlines = []
|
||||
let cur, p
|
||||
for (const c of cmds) {
|
||||
if (c.type == 'Z') continue
|
||||
const q = [p, c.x1 != null && [c.x1, c.y1], c.x2 != null && [c.x2, c.y2], [c.x, c.y]].filter(Boolean)
|
||||
if (c.type == 'M') outlines.push(cur = [[c.x, c.y]])
|
||||
else for (let i = 1, k = max(2, ceil(q.slice(1).reduce((s, v, j) => s + hypot(v[0] - q[j][0], v[1] - q[j][1]), 0))); i <= k; i++) cur.push(bez(q, i / k))
|
||||
p = [c.x, c.y]
|
||||
}
|
||||
const xs = outlines.flat().map(v => v[0]), ys = outlines.flat().map(v => v[1])
|
||||
const xm = (min(...xs) + max(...xs)) / 2, ym = (min(...ys) + max(...ys)) / 2
|
||||
const k = SPAN / ((max(...xs) - min(...xs)) / 2)
|
||||
const word = r => outlines.map(o => poly(o.map(([x, y]) => P((x - xm) * k, LAT + (ym - y) * k * cos(LAT), r))) + 'Z').join('') + islands(r)
|
||||
|
||||
// clouds: soft streaks drifting along latitudes, kept clear of the word
|
||||
const clouds = Array.from({ length: 16 }, () => {
|
||||
const lat = (rnd() < .5 ? -46 + rnd() * 32 : 40 + rnd() * 20) * D, lon = (rnd() * 240 - 120) * D, len = (18 + rnd() * 36) * D
|
||||
const amp = (rnd() - .5) * 5 * D, w = n(4 + rnd() * 8), o = .2 + rnd() * .25
|
||||
const pts = Array.from({ length: 48 }, (_, i) => P(lon + len * i / 47, lat + amp * sin(i / 47 * PI), 1 + RISE * 1.2)).filter(v => v[2] > .1)
|
||||
return pts.length > 3 ? `<path d="${poly(pts)}" stroke-width="${w * 2.4}" opacity="${n(o * 50) / 100}" filter="url(#haze)"/><path d="${poly(pts)}" stroke-width="${w}" opacity="${n(o * 100) / 100}" filter="url(#soft)"/>` : ''
|
||||
}).join('')
|
||||
|
||||
// islands: a small archipelago so the letters read as continents
|
||||
const isles = [[-50, 45, 2.4], [44, 47, 1.7], [-38, -31, 3], [-24, -37, 1.3], [34, -34, 2.2], [50, -27, 1.2]]
|
||||
.map(([lon, lat, rad]) => [lon * D, lat * D, rad * D, rnd() * 9])
|
||||
const islands = r => isles.map(([lon, lat, rad, ph]) => poly(Array.from({ length: 48 }, (_, i) => {
|
||||
const a = i / 48 * 2 * PI, q = rad * (1 + .2 * sin(3 * a + ph) + .1 * sin(5 * a + ph * 2))
|
||||
return P(lon + q * cos(a) / cos(lat), lat + q * sin(a), r)
|
||||
})) + 'Z').join('')
|
||||
|
||||
// relief: stack shells from the sea floor up to the plateau, darkest first
|
||||
const mix = (a, b, t) => '#' + [0, 2, 4].map(i => n(parseInt(a.slice(i + 1, i + 3), 16) * (1 - t) + parseInt(b.slice(i + 1, i + 3), 16) * t) | 0).map(v => v.toString(16).padStart(2, '0')).join('')
|
||||
const relief = Array.from({ length: 9 }, (_, i) => `<path d="${word(1 + RISE * i / 9)}" fill="${mix('#4a1530', '#d2453a', i / 8)}"/>`).join('')
|
||||
|
||||
const cap = poly(Array.from({ length: 180 }, (_, i) => P(i * 2 * D, (75 + 1.6 * sin(i * 2 * D * 5) + .9 * sin(i * 2 * D * 13 + 1)) * D, 1 + RISE * .6))) + 'Z'
|
||||
|
||||
const ring = `<g id="ring" transform="translate(${C} ${C}) scale(1 ${n(sin(T) * 1000) / 1000})">
|
||||
<g fill="none" stroke="url(#ringTone)">
|
||||
${RINGS.flatMap(([a, b, o], _, __, m = ceil((b - a) / .005)) => Array.from({ length: m }, (_, i) => {
|
||||
const r = a + (b - a) * (i + .5) / m
|
||||
return `<circle r="${n(r * R)}" stroke-width="${n((b - a) / m * R + .6)}" opacity="${n(o * (.55 + rnd() * .45) * 100) / 100}"/>`
|
||||
})).join('')}
|
||||
</g></g>`
|
||||
|
||||
const stars = Array.from({ length: 170 }, () => {
|
||||
const x = n(rnd() * S), y = n(rnd() * S), r = rnd() ** 3 * 2.2 + .5, o = n(.25 + rnd() * .75)
|
||||
return r > 2.1
|
||||
? `<path d="M${x} ${y - r * 4}Q${x} ${y} ${x + r * 4} ${y}Q${x} ${y} ${x} ${y + r * 4}Q${x} ${y} ${x - r * 4} ${y}Q${x} ${y} ${x} ${y - r * 4}Z" fill="#fff" opacity="${o}"/>`
|
||||
: `<circle cx="${x}" cy="${y}" r="${n(r)}" fill="#fff" opacity="${o}"/>`
|
||||
}).join('')
|
||||
|
||||
const lx = n(C + L[0] * R * .62), ly = n(C - L[1] * R * .62)
|
||||
const svg = bg => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${S} ${S}" width="${S}" height="${S}">
|
||||
<defs>
|
||||
<radialGradient id="space" cx=".5" cy=".45" r=".75"><stop offset="0" stop-color="#1a1452"/><stop offset=".55" stop-color="#0a0828"/><stop offset="1" stop-color="#030210"/></radialGradient>
|
||||
<radialGradient id="ocean" gradientUnits="userSpaceOnUse" cx="${lx}" cy="${ly}" r="${R * 1.6}"><stop offset="0" stop-color="#7f8cff"/><stop offset=".3" stop-color="#4141e0"/><stop offset=".62" stop-color="#22178f"/><stop offset="1" stop-color="#0c0736"/></radialGradient>
|
||||
<radialGradient id="land" gradientUnits="userSpaceOnUse" cx="${lx}" cy="${ly}" r="${R * 1.5}"><stop offset="0" stop-color="#fff1b8"/><stop offset=".28" stop-color="#ffc25c"/><stop offset=".6" stop-color="#ff7b3d"/><stop offset="1" stop-color="#d43f3a"/></radialGradient>
|
||||
<radialGradient id="shade" gradientUnits="userSpaceOnUse" cx="${lx}" cy="${ly}" r="${R * 1.95}"><stop offset="0" stop-color="#fff" stop-opacity=".22"/><stop offset=".22" stop-color="#fff" stop-opacity="0"/><stop offset=".5" stop-color="#04021a" stop-opacity="0"/><stop offset=".78" stop-color="#04021a" stop-opacity=".62"/><stop offset=".92" stop-color="#04021a" stop-opacity=".92"/></radialGradient>
|
||||
<radialGradient id="rim" cx=".5" cy=".5" r=".5"><stop offset=".8" stop-color="#7fe0ff" stop-opacity="0"/><stop offset=".96" stop-color="#8fe6ff" stop-opacity=".45"/><stop offset="1" stop-color="#d4f7ff" stop-opacity=".85"/></radialGradient>
|
||||
<radialGradient id="halo" cx=".5" cy=".5" r=".5"><stop offset="${n(100 / 1.14) / 100}" stop-color="#6fd0ff" stop-opacity=".55"/><stop offset=".94" stop-color="#5a8cff" stop-opacity=".12"/><stop offset="1" stop-color="#5a8cff" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="lit" gradientUnits="userSpaceOnUse" cx="${lx}" cy="${ly}" r="${R * 1.9}"><stop offset=".3" stop-color="#fff"/><stop offset=".9" stop-color="#222"/></radialGradient>
|
||||
<linearGradient id="ringTone" gradientUnits="userSpaceOnUse" x1="${-R * 1.9}" y1="0" x2="${R * 1.9}" y2="0"><stop offset="0" stop-color="#f4f0ff"/><stop offset=".5" stop-color="#c9c2ff"/><stop offset="1" stop-color="#7d74c9"/></linearGradient>
|
||||
<radialGradient id="moon" cx=".32" cy=".28" r=".85"><stop offset="0" stop-color="#f3eeff"/><stop offset=".5" stop-color="#a99fe0"/><stop offset="1" stop-color="#3a2f7c"/></radialGradient>
|
||||
<radialGradient id="moonGlow"><stop offset=".55" stop-color="#8fe6ff" stop-opacity=".35"/><stop offset="1" stop-color="#5a8cff" stop-opacity="0"/></radialGradient>
|
||||
<radialGradient id="moonShade" cx=".3" cy=".26" r=".95"><stop offset=".45" stop-color="#04021a" stop-opacity="0"/><stop offset="1" stop-color="#04021a" stop-opacity=".85"/></radialGradient>
|
||||
<mask id="litMask" maskUnits="userSpaceOnUse" x="0" y="0" width="${S}" height="${S}"><rect width="${S}" height="${S}" fill="url(#lit)"/></mask>
|
||||
<clipPath id="disc"><circle cx="${C}" cy="${C}" r="${R}"/></clipPath>
|
||||
<clipPath id="back"><rect width="${S}" height="${C}"/></clipPath>
|
||||
<clipPath id="front"><rect y="${C}" width="${S}" height="${C}"/></clipPath>
|
||||
<filter id="soft" x="-20%" y="-20%" width="140%" height="140%"><feGaussianBlur stdDeviation="2.4"/></filter>
|
||||
<filter id="haze" x="-30%" y="-30%" width="160%" height="160%"><feGaussianBlur stdDeviation="6"/></filter>
|
||||
<filter id="shore" x="-10%" y="-10%" width="120%" height="120%"><feGaussianBlur stdDeviation="7"/></filter>
|
||||
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="60"/></filter>
|
||||
</defs>
|
||||
${bg ? `<rect width="${S}" height="${S}" fill="url(#space)"/>
|
||||
<circle cx="${C - 330}" cy="${C - 250}" r="230" fill="#5b3cf5" opacity=".22" filter="url(#glow)"/>
|
||||
<circle cx="${C + 360}" cy="${C + 300}" r="260" fill="#1fb6ff" opacity=".14" filter="url(#glow)"/>
|
||||
${stars}` : ''}
|
||||
<g transform="translate(${C + R * 1.55} ${C - R * 1.2})">
|
||||
<circle r="${R * .22}" fill="url(#moonGlow)"/>
|
||||
<circle r="${R * .13}" fill="url(#moon)"/>
|
||||
<g fill="#3b2f7a" opacity=".35"><ellipse cx="${-R * .04}" cy="${-R * .03}" rx="${R * .028}" ry="${R * .022}"/><ellipse cx="${R * .045}" cy="${R * .02}" rx="${R * .02}" ry="${R * .016}"/><ellipse cx="${-R * .01}" cy="${R * .065}" rx="${R * .015}" ry="${R * .011}"/></g>
|
||||
<circle r="${R * .13}" fill="url(#moonShade)"/>
|
||||
</g>
|
||||
<use href="#ring" clip-path="url(#back)"/>
|
||||
<circle cx="${C}" cy="${C}" r="${R * 1.14}" fill="url(#halo)" mask="url(#litMask)"/>
|
||||
<g clip-path="url(#disc)">
|
||||
<circle cx="${C}" cy="${C}" r="${R}" fill="url(#ocean)"/>
|
||||
<path d="${word(1)}" fill="none" stroke="#6ff0ff" stroke-width="22" stroke-linejoin="round" opacity=".34" filter="url(#shore)"/>
|
||||
<path d="${word(1)}" fill="none" stroke="#9ff6ff" stroke-width="7" stroke-linejoin="round" opacity=".5" filter="url(#soft)"/>
|
||||
${relief}
|
||||
<path d="${word(1 + RISE)}" fill="url(#land)"/>
|
||||
<path d="${cap}" fill="#eef8ff"/>
|
||||
<g fill="none" stroke="#fff" stroke-linecap="round">${clouds}</g>
|
||||
<circle cx="${C}" cy="${C}" r="${R}" fill="url(#shade)"/>
|
||||
<circle cx="${C}" cy="${C}" r="${R}" fill="url(#rim)" mask="url(#litMask)"/>
|
||||
</g>
|
||||
<use href="#ring" clip-path="url(#front)"/>
|
||||
<defs>${ring}</defs>
|
||||
</svg>`
|
||||
|
||||
for (const [name, bg] of [['logo', 1], ['logo-transparent', 0]]) {
|
||||
const s = svg(bg)
|
||||
writeFileSync(at(name + '.svg'), s)
|
||||
writeFileSync(at(name + '.png'), new Resvg(s, { fitTo: { mode: 'width', value: 2048 }, background: bg ? '#030210' : undefined }).render().asPng())
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 374 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 MiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 387 KiB |
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "renox-as-planet-blue",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "Renox as a planet, blue ocean version",
|
||||
"scripts": {
|
||||
"build": "bun index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/unbounded": "^5.3.0",
|
||||
"@resvg/resvg-js": "^2.6.2",
|
||||
"opentype.js": "^2.0.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user