bgleam/index.html

493 lines
32 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1.0">
<meta name="color-scheme" content="dark">
<link rel="shortcut icon" href="https://gleam.run/images/lucy/lucy.svg">
<title>BGleam</title>
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
font-family: sans-serif;
background-color: #1c1b22;
}
body {
display: flex;
}
#sidebar {
width: 28rem;
min-width: 28rem;
height: 100%;
user-select: none;
border-right: 2px solid white;
display: flex;
flex-direction: column;
}
#sidebar header {
padding: 1rem;
border-bottom: 2px solid white;
}
#sidebar h2, #sidebar p {
margin: 0;
text-align: center;
}
#sidebar p {
font-size: 0.8rem;
margin-top: 0.5rem;
}
#settings {
flex-grow: 1;
padding: 1rem;
display: grid;
grid-gap: 1rem;
grid-template-columns: [label] min-content [maininput] 1fr [subinput] 4.2rem [end];
grid-template-rows: auto;
align-items: center;
align-content: start;
overflow-y: auto;
}
#settings label {
grid-column: label;
white-space: nowrap;
}
#settings input, #settings select {
font-size: 0.9rem;
width: 100%;
box-sizing: border-box;
}
#settings select {
grid-column-start: maininput;
grid-column-end: end;
padding: 0.4rem 0.6rem;
}
#settings input[type="range"] {
grid-column: maininput;
}
#settings input[type="number"] {
grid-column: subinput;
padding: 0.4rem 0.6rem;
padding-right: 0;
}
#settings input[type="text"] {
grid-column: maininput;
padding: 0.4rem 0.6rem;
}
#settings input[type="checkbox"] {
grid-column: maininput;
width: 1.2rem;
height: 1.2rem;
}
#settings input[type="color"] {
grid-column: subinput;
height: 100%;
padding: 0.2rem;
}
#settings .checkboxGroup {
grid-column-start: maininput;
grid-column-end: end;
display: flex;
align-items: center;
}
#settings .checkboxGroup input[type="checkbox"] {
margin-left: 0.5rem;
margin-right: 1rem;
}
#settings .checkboxGroup input[type="checkbox"]:last-child {
margin-right: 0;
}
#saveButtonContainer {
width: 100%;
grid-column-start: label;
grid-column-end: end;
display: flex;
}
#saveSVGButton, #savePNGButton {
font-size: 1.2rem;
font-weight: bold;
width: 100%;
padding: 1rem;
cursor: pointer;
text-align: center;
text-decoration: none;
box-sizing: border-box;
background-color: #2b2a33;
color: white;
}
#saveSVGButton:hover, #savePNGButton:hover {
background-color: #52525e;
}
#colorSchemeInputs, #vignetteInputs {
display: contents;
}
#colorSchemeInputs.hidden, #vignetteInputs.hidden {
display: none;
}
#preview {
flex-grow: 1;
overflow: hidden;
}
#preview svg {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="sidebar">
<header>
<h2>Gleam Background Settings</h2>
<p>Credit to <a href="https://github.com/giacomocavalieri">Jak</a> for the original design idea.</p>
</header>
<form id="settings" oninput="updatePreview()" onchange="updateSaveHrefs()">
<label for="width">Width</label>
<input name="widthSlider" type="range" min="200" max="8192" value="1920" oninput="this.form.width.value = this.value">
<input id="width" name="width" type="number" min="200" max="8192" value="1920" oninput="this.form.widthSlider.value = this.value">
<label for="height">Height</label>
<input name="heightSlider" type="range" min="200" max="8192" value="1080" oninput="this.form.height.value = this.value">
<input id="height" name="height" type="number" min="200" max="8192" value="1080" oninput="this.form.heightSlider.value = this.value">
<label for="logoScale">Logo Scale</label>
<input name="logoScaleSlider" type="range" min="0.1" max="8" step=".01" value="0.7" oninput="this.form.logoScale.value = this.value">
<input id="logoScale" name="logoScale" type="number" min="0.1" max="8" step=".01" value="0.7" oninput="this.form.logoScaleSlider.value = this.value">
<label for="logoRotation">Logo Rotation</label>
<input name="logoRotationSlider" type="range" min="0" max="360" step=".5" value="348" oninput="this.form.logoRotation.value = this.value">
<input id="logoRotation" name="logoRotation" type="number" min="0" max="360" step=".5" value="348" oninput="this.form.logoRotationSlider.value = this.value">
<label for="patternScale">Pattern Scale</label>
<input name="patternScaleSlider" type="range" min="0.1" max="8" step=".01" value="1" oninput="this.form.patternScale.value = this.value">
<input id="patternScale" name="patternScale" type="number" min="0.1" max="8" step=".01" value="1" oninput="this.form.patternScaleSlider.value = this.value">
<label for="patternSpacing">Pattern Spacing</label>
<input name="patternSpacingSlider" type="range" min="1" max="4" step=".01" value="1.1" oninput="this.form.patternSpacing.value = this.value">
<input id="patternSpacing" name="patternSpacing" type="number" min="1" max="4" step=".01" value="1.1" oninput="this.form.patternSpacingSlider.value = this.value">
<label for="patternRotation">Pattern Rotation</label>
<input name="patternRotationSlider" type="range" min="0" max="360" step=".5" value="325" oninput="this.form.patternRotation.value = this.value">
<input id="patternRotation" name="patternRotation" type="number" min="0" max="360" step=".5" value="325" oninput="this.form.patternRotationSlider.value = this.value">
<label for="patternLucyRotation">Pattern Lucy Rotation</label>
<input name="patternLucyRotationSlider" type="range" min="0" max="360" step=".5" value="17.5" oninput="this.form.patternLucyRotation.value = this.value">
<input id="patternLucyRotation" name="patternLucyRotation" type="number" min="0" max="360" step=".5" value="17.5" oninput="this.form.patternLucyRotationSlider.value = this.value">
<label>Flag Lucy</label>
<select id="flagLucy" name="flagLucy">
<option value="none" selected>None</option>
<option value="pride">Pride (rainbow)</option>
<option value="trans">Trans Pride</option>
<option value="lesbian">Lesbian Pride</option>
<option value="gay">Gay Pride</option>
<option value="bi">Bi Pride</option>
</select>
<label>Winking Lucy</label>
<div class="checkboxGroup">
<label for="winkingLucyLEnabled">Left Eye</label>
<input id="winkingLucyLEnabled" name="winkingLucyLEnabled" type="checkbox">
<label for="winkingLucyREnabled">Right Eye</label>
<input id="winkingLucyREnabled" name="winkingLucyREnabled" type="checkbox">
</div>
<label for="sleepyLucyEnabled">Sleepy Lucy</label>
<input id="sleepyLucyEnabled" name="sleepyLucyEnabled" type="checkbox">
<label for="colorScheme">Color Scheme</label>
<select id="colorScheme" name="colorScheme">
<option value="light" selected>Light</option>
<option value="dark">Dark</option>
<option value="blurple">Blurple</option>
<option value="custom">Custom</option>
</select>
<div id="colorSchemeInputs" class="hidden">
<label for="textPrimaryColor">Text Primary Color</label>
<input id="textPrimaryColor" name="textPrimaryColor" type="text" value="#ffaff3" oninput="this.form.textPrimaryColorPicker.value = normalizeColor(this.value)">
<input name="textPrimaryColorPicker" type="color" value="#ffaff3" oninput="this.form.textPrimaryColor.value = this.value">
<label for="textShadowColor">Text Shadow Color</label>
<input id="textShadowColor" name="textShadowColor" type="text" value="#a6f0fc" oninput="this.form.textShadowColorPicker.value = normalizeColor(this.value)">
<input name="textShadowColorPicker" type="color" value="#a6f0fc" oninput="this.form.textShadowColor.value = this.value">
<label for="lucyColor">Lucy Color</label>
<input id="lucyColor" name="lucyColor" type="text" value="#ffaff3" oninput="this.form.lucyColorPicker.value = normalizeColor(this.value)">
<input name="lucyColorPicker" type="color" value="#ffaff3" oninput="this.form.lucyColor.value = this.value">
<label for="lucyFaceColor">Lucy Face Color</label>
<input id="lucyFaceColor" name="lucyFaceColor" type="text" value="#fefefc" oninput="this.form.lucyFaceColorPicker.value = normalizeColor(this.value)">
<input name="lucyFaceColorPicker" type="color" value="#fefefc" oninput="this.form.lucyFaceColor.value = this.value">
<label for="lambdaColor">Lambda Color</label>
<input id="lambdaColor" name="lambdaColor" type="text" value="#a6f0fc" oninput="this.form.lambdaColorPicker.value = normalizeColor(this.value)">
<input name="lambdaColorPicker" type="color" value="#a6f0fc" oninput="this.form.lambdaColor.value = this.value">
<label for="outlineColor">Outline Color</label>
<input id="outlineColor" name="outlineColor" type="text" value="#fefefc" oninput="this.form.outlineColorPicker.value = normalizeColor(this.value)">
<input name="outlineColorPicker" type="color" value="#fefefc" oninput="this.form.outlineColor.value = this.value">
<label for="backgroundColor">BG Color</label>
<input id="backgroundColor" name="backgroundColor" type="text" value="#fcc3fb" oninput="this.form.backgroundColorPicker.value = normalizeColor(this.value)">
<input name="backgroundColorPicker" type="color" value="#fcc3fb" oninput="this.form.backgroundColor.value = this.value">
<label for="backgroundLucyColor">BG Lucy Color</label>
<input id="backgroundLucyColor" name="backgroundLucyColor" type="text" value="#fdb7f6" oninput="this.form.backgroundLucyColorPicker.value = normalizeColor(this.value)">
<input name="backgroundLucyColorPicker" type="color" value="#fdb7f6" oninput="this.form.backgroundLucyColor.value = this.value">
</div>
<label for="vignetteEnabled">Vignette</label>
<input id="vignetteEnabled" name="vignetteEnabled" type="checkbox">
<div id="vignetteInputs" class="hidden">
<label for="vignetteColor">Vignette Color</label>
<input id="vignetteColor" name="vignetteColor" type="text" value="#916dab" oninput="this.form.vignetteColorPicker.value = normalizeColor(this.value)">
<input name="vignetteColorPicker" type="color" value="#916dab" oninput="this.form.vignetteColor.value = this.value">
<label for="vignetteStart">Vignette Start</label>
<input name="vignetteStartSlider" type="range" min="0" max="2" step=".01" value="0.3" oninput="this.form.vignetteStart.value = this.value">
<input id="vignetteStart" name="vignetteStart" type="number" min="0" max="2" step=".01" value="0.3" oninput="this.form.vignetteStartSlider.value = this.value">
<label for="vignetteEnd">Vignette End</label>
<input name="vignetteEndSlider" type="range" min="0" max="2" step=".01" value="0.7" oninput="this.form.vignetteEnd.value = this.value">
<input id="vignetteEnd" name="vignetteEnd" type="number" min="0" max="2" step=".01" value="0.7" oninput="this.form.vignetteEndSlider.value = this.value">
<label for="vignetteBlendMode">Vignette Blend Mode</label>
<select id="vignetteBlendMode" name="vignetteBlendMode">
<option value="normal">Normal</option>
<option value="multiply" selected>Multiply</option>
<option value="screen">Screen</option>
<option value="overlay">Overlay</option>
<option value="darken">Darken</option>
<option value="lighten">Lighten</option>
<option value="color-dodge">Color Dodge</option>
<option value="color-burn">Color Burn</option>
<option value="hard-light">Hard Light</option>
<option value="soft-light">Soft Light</option>
<option value="difference">Difference</option>
<option value="exclusion">Exclusion</option>
<option value="hue">Hue</option>
<option value="saturation">Saturation</option>
<option value="color">Color</option>
<option value="luminosity">Luminosity</option>
<option value="plus-darker">Plus Darker</option>
<option value="plus-lighter">Plus Lighter</option>
</select>
</div>
</form>
<div id="saveButtonContainer">
<a id="saveSVGButton" href="#" download="gleam-background.svg">Save SVG</a>
<a id="savePNGButton" href="#" download="gleam-background.png">Save PNG</a>
</div>
</div>
<div id="preview"></div>
<script>
const createSVG = ({
width, height, logoScale, logoRotation, patternScale, patternSpacing, patternRotation,
patternLucyRotation, winkingLucyLEnabled, winkingLucyREnabled, sleepyLucyEnabled, flagLucy,
colorScheme, vignetteEnabled, vignetteColor, vignetteStart, vignetteEnd, vignetteBlendMode,
}) =>
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}">
<defs>
<path id="lucy" d="M905.5 137.63c41.483-73.507 147.51-73.507 189 0l217.42 385.27c26.9 47.672 73.23 81.278 126.9 92.095l434.05 87.471c82.87 16.699 115.52 117.34 58.4 179.4l-299.67 325.58a188.15 188.15 0 0 0-48.49 149.06l50.83 439.33c9.69 83.71-75.98 146.04-152.89 110.88l-402.64-184.05a188.55 188.55 0 0 0-156.82 0l-402.63 184.05c-76.916 35.15-162.58-27.17-152.9-110.88l50.837-439.33c6.292-54.37-11.413-108.78-48.488-149.06l-299.68-325.58c-57.118-62.055-24.463-162.7 58.403-179.4l434.05-87.471c53.674-10.817 100-44.423 126.9-92.095z"/>
<pattern id="lucy-pattern" patternUnits="userSpaceOnUse" width="${200 * patternScale * patternSpacing}" height="${200 * patternScale * patternSpacing}" patternTransform="rotate(${patternRotation})">
<use href="#lucy" fill="${colorScheme.backgroundLucy}" transform="scale(${patternScale / 10}) translate(${1000 * patternSpacing - 1000} ${1000 * patternSpacing - 1000}) rotate(${patternLucyRotation} 1000 1000)"/>
</pattern>${vignetteEnabled ? `
<radialGradient id="vignette" fx="50%" fy="50%" r="100%">
<stop offset="${vignetteStart * 100}%" stop-color="${vignetteColor}" stop-opacity="0.0"/>
<stop offset="${vignetteEnd * 100}%" stop-color="${vignetteColor}" stop-opacity="1.0"/>
</radialGradient>` : ""}
<path id="gleam" d="M98.28 3.78c-27.603 0-95.41 15.403-95.41 86.811 0 54.607 43.005 87.21 87.611 87.21 41.605 0 82.809-28.402 82.809-76.408 0-20.003-5.599-30.004-21.401-30.004-2.4 0-30.604 1.199-52.407 2.399-3.6.2-6.202 3-6.202 6.001v.4l.4 23.804c0 3 1.8 6.2 5.6 6.2h.4c4.801-.2 18.403-1.199 20.803-1.199h.6c2 0 2.801.999 2.801 2.799 0 5.601-9.803 19.604-29.605 19.604-18.802 0-37.005-14.802-37.005-40.406 0-19.802 10.602-42.005 42.806-42.005 8.401 0 16.202 1.799 21.003 4.2.6.4 1.4.6 2 .6 2.4 0 4.401-1.8 4.801-3.6l6.8-33.604v-.801c0-2.4-1.399-4.599-3.2-5.399-9.401-4.401-21.004-6.603-33.205-6.603zm100.413-1.399c-2.2 0-4 1.799-4 4.2v163.421c0 2.2 1.8 4 4 4h40.206c2.2 0 4-1.8 4-4v-163.421c0-2.4-1.8-4.2-4-4.2zm132.616 55.606c-45.606 0-65.807 30.003-65.807 58.607 0 30.404 22.802 61.408 68.208 61.408h2.401c5.801 0 8.401-2.8 10.001-6.001 3-6.801 8.202-20.403 8.202-22.403 0-3.4-3.402-5.2-6.202-5.2h-.4c-1.4.2-2.999.199-4.399.199-25.003 0-35.405-16.001-35.405-30.203 0-12.401 8.001-20.803 17.602-20.803 8.401 0 12.201 6.4 12.201 8.2 0 2.8-1.399 3.202-11.8 5.602-2.6.6-4.202 1.599-4.202 3.799 0 .8 3.802 13.802 6.202 20.403.8 2.4 1.8 3.801 5.001 3.801 10.401-.4 25.203-2.601 34.604-5.802 11.802-4 15.602-11.602 15.602-20.803 0-6.601-2.201-50.805-51.807-50.805zm121.015-.801c-39.605 0-56.607 34.604-56.607 58.607 0 32.204 28.805 57.808 62.209 57.808 10.201 0 21.003-2.401 31.404-7.802 10.001 9.401 24.003 12.603 26.003 12.603 2.6 0 4.599-1.802 6.399-5.202l12.402-24.202c.4-.8.6-1.401.6-1.801 0-2-2.2-3.2-4.2-4.2-6.401-3.4-8.601-12.001-8.601-24.003 0-13.202 2.8-30.605 5.6-48.807v-1c0-2.4-1.4-5.001-6.6-5.401l-34.604-3h-1c-2.4 0-4.201.6-5.401 2-7.801-3.4-17.604-5.6-27.605-5.6zm9.202 36.805c5.801 0 11.201 2.799 13.601 6.8-.4 6.001-.6 11.403-.6 16.604 0 6.201.4 11.802 1 17.002-4.601 2-9.002 2.799-12.802 2.799-13.002 0-20.801-9.6-20.801-20.801 0-10.201 7.001-22.403 19.602-22.403zm196.425-36.604c-11.201 0-23.404 2.2-36.206 7.001-7.801-3-16.201-4.401-25.202-4.401-9.601 0-19.603 1.6-29.805 5.001l-12.001.6c-2 .2-3.6 1.8-3.6 4v.4l5.001 104.013c.2 2.2 1.801 4 3.801 4h.4l37.403-1.801c2.2-.2 3.801-2.001 3.801-4.401l-3.6-72.609c12.602 1 16.801 9.401 17.801 29.603l2 42.206c.2 2.2 1.801 4 3.801 4h.4l37.204-2c2.2-.2 3.801-2.001 3.801-4.401l-3.6-71.409c11.401 1.6 15.602 9.602 16.602 31.205 2.4 39.405 33.804 45.605 36.604 45.605 2 0 3.8-.801 6.001-2.801 0 0 17.002-16.202 17.002-16.602 1.2-1 1.6-2.2 1.6-3.2 0-2.2-2.4-4.202-3.6-5.202-9.401-7.401-11.602-17.201-12.402-30.203-2.2-36.404-28.003-58.607-63.207-58.607z"/>
<path id="kirakira" d="M250 218c-2.591.392-9.658 1.021-13.74 1.492-1.256.235-1.883 1.256-1.883 2.119 0 .471.706 5.416 1.02 7.929l-12.326-.313c-1.021 0-1.805.706-1.805 1.727l-.158 11.07v.156c0 .864.707 1.57 1.649 1.649l14.84.393 1.176 8.009-19.235 1.1c-.864.079-1.176.705-1.176 1.569v.236l.549 11.07c.079 1.021.863 1.727 1.805 1.727l20.256-1.178 2.827 18.922c.157.864 1.021 1.649 2.041 1.649h.156l13.269-.785c1.021-.079 1.649-.865 1.649-1.807 0-.079-.002-5.181-1.336-19.076l16.096-.944c.942 0 1.649-.784 1.649-1.805l-.551-10.992c-.079-.942-1.256-1.727-2.119-1.727h-.156l-16.567.942-.785-6.439 12.562.315c.942 0 1.807-.707 1.807-1.649l.156-11.07v-.156c0-.942-.785-1.649-1.649-1.649l-14.918-.393c-.707-4.24-1.334-7.774-1.883-10.365-.157-.864-1.022-1.727-2.67-1.727zm60.138.863c-1.021 0-1.884.786-2.041 1.807l-.942 11.54v.156c0 .942.863 1.963 1.883 1.963 8.087.235 21.434 1.1 31.326 1.414h.156c1.021 0 1.963-.786 2.041-1.807l.863-11.933v-.156c0-.942-.784-1.885-1.805-1.963-7.145-.314-22.69-.708-31.326-1.022zm-10.206 20.571c-.785 0-1.492.627-1.571 1.412l-1.178 12.326v.158c0 .785.629 1.412 1.414 1.49l30.775 2.512c.471.079 1.256.157 1.256 1.178 0 1.649-4.867 13.741-10.285 22.612-.235.471-.393.783-.393 1.176 0 .864.785 1.335 1.571 1.649l9.892 3.612c.392.157.707.236 1.1.236 1.177 0 2.198-.707 2.59-1.1 13.425-13.033 17.979-31.326 17.979-35.958 0-4.318-3.376-7.458-8.165-7.851l-44.83-3.453zm107.088-21.434c-2.591.392-9.658 1.021-13.74 1.492-1.256.235-1.883 1.256-1.883 2.119 0 .471.706 5.416 1.02 7.929l-12.326-.313c-1.021 0-1.805.706-1.805 1.727l-.158 11.07v.156c0 .864.707 1.57 1.649 1.649l14.84.393 1.176 8.009-19.235 1.1c-.864.079-1.176.705-1.176 1.569v.236l.549 11.07c.079 1.021.863 1.727 1.805 1.727l20.257-1.178 2.827 18.922c.157.864 1.021 1.649 2.041 1.649h.156l13.269-.785c1.021-.079 1.649-.865 1.649-1.807 0-.079-.002-5.181-1.336-19.076l16.096-.944c.942 0 1.649-.784 1.649-1.805l-.551-10.992c-.079-.942-1.256-1.727-2.119-1.727h-.156l-16.567.942-.785-6.439 12.562.315c.942 0 1.807-.707 1.807-1.649l.156-11.07v-.156c0-.942-.785-1.649-1.649-1.649l-14.918-.393c-.707-4.24-1.334-7.774-1.883-10.365-.157-.864-1.021-1.727-2.67-1.727zm60.138.863c-1.021 0-1.884.786-2.041 1.807l-.942 11.54v.156c0 .942.863 1.963 1.883 1.963 8.087.235 21.434 1.1 31.326 1.414h.157c1.021 0 1.963-.786 2.041-1.807l.863-11.933v-.156c0-.942-.784-1.885-1.805-1.963-7.145-.314-22.69-.708-31.326-1.022zm-10.206 20.571c-.785 0-1.492.627-1.571 1.412l-1.178 12.326v.158c0 .785.629 1.412 1.414 1.49l30.775 2.512c.471.079 1.256.157 1.256 1.178 0 1.649-4.867 13.741-10.285 22.612-.235.471-.393.783-.393 1.176 0 .864.785 1.335 1.571 1.649l9.892 3.612c.392.157.707.236 1.1.236 1.177 0 2.198-.707 2.59-1.1 13.425-13.033 17.979-31.326 17.979-35.958 0-4.318-3.376-7.458-8.165-7.851l-44.83-3.453z"/>
<path id="lambda" d="M29 2.28c-4.369 0-6.16.448-6.944 2.576l-5.153 14.115c-.112.448-.223.783-.223 1.119 0 1.568 1.792 1.68 3.696 1.68 6.945 0 11.874 1.457 13.33 8.401l3.135 13.666-10.529-4.032c-.112-.112-.335-.113-.447-.113-1.232 0-2.801 1.12-3.137 2.241l-20.163 49.174c-.112.224-.111.448-.111.672 0 1.232.783 2.577 1.791 2.801l19.043 5.376c.112 0 .337.113.561.113 1.12 0 2.688-.898 3.248-2.018 3.92-6.497 9.857-18.706 15.01-31.699l3.471 15.234c4.145 17.81 20.723 19.713 24.98 19.713 1.344 0 2.689-.446 3.809-2.239 0 0 7.504-11.203 7.392-11.539.448-.672.672-1.344.672-1.905 0-1.456-1.231-2.24-2.127-2.576-4.257-1.456-9.186-5.936-10.306-11.201l-11.089-50.407c-3.136-14.338-16.018-19.155-29.908-19.155z"/>
<g id="logo" transform="scale(${logoScale}) translate(-360 -180) rotate(${logoRotation} 360 180)" stroke-linecap="round" stroke-linejoin="round">
<g fill="none" stroke="${colorScheme.outline}" stroke-width="67.5">
<path d="M600 230h80z"/>
<use href="#lucy" stroke-width="520" transform="translate(518 208) scale(0.13) rotate(31 1000 1000)"/>
<use href="#lucy" stroke-width="1125" transform="translate(245 -85) scale(0.06) rotate(-20 1000 1000)"/>
<use href="#gleam"/>
<use href="#kirakira"/>
<g transform="translate(-18 13)">
<use href="#gleam"/>
<use href="#kirakira"/>
</g>
<use href="#lambda" stroke-width="99" transform="translate(702 -12) scale(0.683)"/>
<use href="#lambda" transform="translate(10 196) rotate(24)"/>
</g>
<g transform="translate(518 208) scale(0.13) rotate(31 1000 1000)">${flagLucy !== undefined ? `
<mask id="lucy-mask" width="2000" height="2000" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha">
<use href="#lucy"/>
</mask>
<g mask="url(#lucy-mask)">${(h => flagLucy.map((c, i) => `
<path fill="${c}" d="M0 ${i * h + 82}h2000v${h}h-2000z" />`).join())(1835 / flagLucy.length)}
</g>` : `
<use href="#lucy" fill="${colorScheme.lucy}" stroke="none"/>`}
<path fill="none" stroke="${colorScheme.lucyFace}" stroke-width="80" d="M937 1194c16 69 110 69 126 0"/>${sleepyLucyEnabled ? `
<path fill="none" stroke="${colorScheme.lucyFace}" stroke-width="80" d="M607 994c16 69 110 69 126 0"/>
<path fill="none" stroke="${colorScheme.lucyFace}" stroke-width="80" d="M1267 994c16 69 110 69 126 0"/>` : `${winkingLucyLEnabled ? `
<path fill="none" stroke="${colorScheme.lucyFace}" stroke-width="80" d="M613 978.5l85 50l-85 50"/>` : `
<circle fill="${colorScheme.lucyFace}" stroke="none" cx="678.6" cy="1049.6" r="78.571"/>`}${winkingLucyREnabled ? `
<path fill="none" stroke="${colorScheme.lucyFace}" stroke-width="80" d="M1387 978.5l-85 50l85 50"/>` : `
<circle fill="${colorScheme.lucyFace}" stroke="none" cx="1321.4" cy="1049.6" r="78.571"/>`}`}
</g>
<g fill="${colorScheme.textShadow}" stroke="none" transform="translate(-18 13)">
<use href="#gleam"/>
<use href="#kirakira"/>
</g>
<g fill="${colorScheme.lambda}" stroke="none">
<use href="#lambda" transform="translate(702 -12) scale(0.683)"/>
<use href="#lambda" transform="translate(10 196) rotate(24)"/>
</g>
<g fill="${colorScheme.textPrimary}" stroke="${colorScheme.outline}" stroke-width="6.5">
<use href="#gleam"/>
<use href="#kirakira"/>
</g>
<use href="#lucy" fill="${colorScheme.lucy}" stroke="none" transform="translate(245 -85) scale(0.06) rotate(-20 1000 1000)"/>
</g>
</defs>
<rect fill="${colorScheme.background}" width="100%" height="100%"/>
<rect fill="url(#lucy-pattern)" width="100%" height="100%"/>${vignetteEnabled ? `
<rect fill="url(#vignette)" width="100%" height="100%" style="mix-blend-mode:${vignetteBlendMode}"/>` : ""}
<use href="#logo" x="50%" y="50%"/>
</svg>`
const colorSchemes = new Map(Object.entries({
light: {
textPrimary: "#ffaff3",
textShadow: "#a6f0fc",
lucy: "#ffaff3",
lucyFace: "#fefefc",
lambda: "#a6f0fc",
outline: "#fefefc",
background: "#fcc3fb",
backgroundLucy: "#fdb7f6",
},
dark: {
textPrimary: "#2f2f2f",
textShadow: "#faaff3",
lucy: "#ffaff3",
lucyFace: "#2f2f2f",
lambda: "#2f2f2f",
outline: "#fefefc",
background: "#2f2f2f",
backgroundLucy: "#202020",
},
blurple: {
textPrimary: "#b3bbe2",
textShadow: "#a2f7e3",
lucy: "#b3bbe2",
lucyFace: "#ffffff",
lambda: "#a2f7e3",
outline: "#ffffff",
background: "#b8d7e2",
backgroundLucy: "#b5c5e2",
},
}))
const flagColors = new Map(Object.entries({
pride: ["#f57189", "#ffb783", "#f0e68e", "#a3eb9e", "#a0d9e2", "#c1adf8"],
trans: ["#5bcefa", "#f5a9b8", "#ffffff", "#f5a9b8", "#5bcefa"],
lesbian: ["#d52d00", "#ff9a56", "#ffffff", "#d362a4", "#a30262"],
gay: ["#3d8a72", "#a8e5c3", "#ffffff", "#83addf", "#372274"],
bi: ["#d60270", "#9b4f96", "#0038a8"],
}))
const form = document.getElementById("settings")
const colorSchemeInputs = document.getElementById("colorSchemeInputs")
const vignetteInputs = document.getElementById("vignetteInputs")
const saveSVGButton = document.getElementById("saveSVGButton")
const savePNGButton = document.getElementById("savePNGButton")
const preview = document.getElementById("preview")
const canvas = document.createElement("canvas")
const ctx = canvas.getContext("2d")
const img = document.createElement("img")
const normalizeColor = color => {
ctx.fillStyle = color
const m = ctx.fillStyle.match(/rgba\((.*?), (.*?), (.*?), .*?\)/)
if (m) ctx.fillStyle = `rgb(${m[1]}, ${m[2]}, ${m[3]})`
return ctx.fillStyle
}
const getFormData = () => {
const formData = new FormData(form)
const width = +formData.get("width")
const height = +formData.get("height")
const logoScale = +formData.get("logoScale")
const logoRotation = +formData.get("logoRotation")
const patternScale = +formData.get("patternScale")
const patternSpacing = +formData.get("patternSpacing")
const patternRotation = +formData.get("patternRotation")
const patternLucyRotation = +formData.get("patternLucyRotation")
const winkingLucyLEnabled = !!formData.get("winkingLucyLEnabled")
const winkingLucyREnabled = !!formData.get("winkingLucyREnabled")
const sleepyLucyEnabled = !!formData.get("sleepyLucyEnabled")
const flagLucyName = `${formData.get("flagLucy")}`
const flagLucy = flagColors.get(flagLucyName)
const colorSchemeName = `${formData.get("colorScheme")}`
const isCustomColorScheme = colorSchemeName === "custom"
const colorScheme = isCustomColorScheme ? {
textPrimary: `${formData.get("textPrimaryColor")}`,
textShadow: `${formData.get("textShadowColor")}`,
lucy: `${formData.get("lucyColor")}`,
lucyFace: `${formData.get("lucyFaceColor")}`,
lambda: `${formData.get("lambdaColor")}`,
outline: `${formData.get("outlineColor")}`,
background: `${formData.get("backgroundColor")}`,
backgroundLucy: `${formData.get("backgroundLucyColor")}`,
} : {
...colorSchemes.get(colorSchemeName),
...(flagLucy === undefined ? {} : { lucyFace: "#151515" })
}
const vignetteEnabled = !!formData.get("vignetteEnabled")
const vignetteColor = `${formData.get("vignetteColor")}`
const vignetteStart = +formData.get("vignetteStart")
const vignetteEnd = +formData.get("vignetteEnd")
const vignetteBlendMode = `${formData.get("vignetteBlendMode")}`
const props = {
width, height, logoScale, logoRotation, patternScale, patternSpacing, patternRotation,
patternLucyRotation, winkingLucyLEnabled, winkingLucyREnabled, sleepyLucyEnabled, flagLucy,
colorScheme, vignetteEnabled, vignetteColor, vignetteStart, vignetteEnd, vignetteBlendMode,
}
const svg = createSVG(props)
return { ...props, flagLucyName, colorSchemeName, isCustomColorScheme, svg }
}
let curData = getFormData()
const updatePreview = () => {
curData = getFormData()
if (curData.isCustomColorScheme) colorSchemeInputs.classList.remove("hidden")
else colorSchemeInputs.classList.add("hidden")
if (curData.vignetteEnabled) vignetteInputs.classList.remove("hidden")
else vignetteInputs.classList.add("hidden")
preview.innerHTML = curData.svg
}
updatePreview()
const updateSaveHrefs = () => {
savePNGButton.setAttribute("href", "#")
saveSVGButton.setAttribute("href", "#")
const svgBlob = new Blob([curData.svg], { type: "image/svg+xml" })
const svgUrl = window.URL.createObjectURL(svgBlob)
saveSVGButton.setAttribute("href", svgUrl)
img.width = curData.width
img.height = curData.height
canvas.width = curData.width
canvas.height = curData.height
img.onload = () => {
ctx.drawImage(img, 0, 0, curData.width, curData.height)
canvas.toBlob(pngBlob => {
const pngUrl = window.URL.createObjectURL(pngBlob)
savePNGButton.setAttribute("href", pngUrl)
}, "image/png")
}
img.src = svgUrl
}
updateSaveHrefs()
</script>
</body>
</html>