feat: add png download button

This commit is contained in:
s3lph 2024-01-24 13:47:13 +01:00
parent 79b9261b51
commit 5c517696a4

View file

@ -12,7 +12,10 @@
</style> </style>
</head> </head>
<body> <body>
<h1>Antifa-Sticker-Generator</h1> <h1>Antifa Sticker Generator</h1>
<p>
A purely client-side sticker generator. <a href="https://git.kabelsalat.ch/s3lph/antifa-sticker-generator">Source Code.</a>
</p>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" width="500" height="500" id="svg"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" width="500" height="500" id="svg">
<style> <style>
text { text {
@ -42,14 +45,16 @@
<path id="upper" stroke="red" fill="none" d="M 40 250 A 210 210 0 0 1 460 250" /> <path id="upper" stroke="red" fill="none" d="M 40 250 A 210 210 0 0 1 460 250" />
<path id="lower" stroke="red" fill="none" d="M 10 250 A 230 230 0 0 0 490 250" /> <path id="lower" stroke="red" fill="none" d="M 10 250 A 230 230 0 0 0 490 250" />
</defs> </defs>
<circle id="bleed" cx="250" cy="250" r="249" stroke="#ff00ff" fill="none" stroke-width="0" /> <g id="svgroot" transform="scale(1, 1)">
<circle cx="250" cy="250" r="225" stroke="black" fill="white" stroke-width="50" /> <circle id="bleed" cx="250" cy="250" r="249" stroke="#ff00ff" fill="none" stroke-width="0" />
<g id="icon"> <circle cx="250" cy="250" r="225" stroke="black" fill="white" stroke-width="50" />
<image transform="translate(0 0) translate(-9 -2) scale(1, 1)" id="iconred" href="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iNTEycHgiCiAgICAgaGVpZ2h0PSI1MTJweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGZpbGw9IiMwMDAwMDAiIGQ9Ik0xMjUuNjY3LDEyMi45MTdjMCwwLDI4LDMzLjA4Myw4OS4yNSwzNC4zMzNjNjEuMjUxLDEuMjUsOTUuOTE3LTM3LjkxNywxMzAuOTE3LTMzLjMzM3M2Myw0My4zMzMsNzcuNzUsNTAuMTY3TDMzMyw0MjUuNzUKICAgICAgICBjMCwwLTEuODMzLDEuMzM0LTExLDQuNjY3cy0xMS4zMzMsNC4zMzMtMTEuMzMzLDQuMzMzbDQwLjI1LTEyMi45MTdjMCwwLTM4Ljc1LTMyLjY4Ny03My43NS0zNQogICAgICAgIGMtMzUuMDAxLTIuMzEzLTUwLjkxNywyMy43NS0xMTAuMDgzLDEzLjc1QzEwNy45MTcsMjgwLjU4Myw2OS41LDI0My41LDY5LjUsMjQzLjVzLTEuNDE1LTIxLjA2NywxNC41LTU5LjgzMwogICAgICAgIEM5OS45MTQsMTQ0LjkwMiwxMjUuNjY3LDEyMi45MTcsMTI1LjY2NywxMjIuOTE3eiIvPgo8L3N2Zz4K" width="512" height="512" filter="url(#red)" /> <g id="icon">
<image transform="translate(0 0) translate(-9 -2) scale(1, 1)" id="iconblack" href="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iNTEycHgiCiAgICAgaGVpZ2h0PSI1MTJweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGZpbGw9IiMwMDAwMDAiIGQ9Ik02OS45MTcsMjUxLjI1YzAsMCw0MS4wODQsMzguNDE2LDEwMi40MTcsNDYuMDgzYzYxLjMzMiw3LjY2Nyw2Ny4wMzktMTQuNDkxLDEwMC45MTYtMTQuMjUKICAgICAgICBjMjEuNTQ4LDAuMTUzLDI5LjMzNCw5LjU4NCwyOS4zMzQsOS41ODRsLTUzLjUwNiwxNDkuNjdjMCwwLTQuMTgtMC4wNDQtMTAuMDkyLTAuNjkyYy01LjkxMS0wLjY0OC05LjU0MS0xLjI5NC05LjU0MS0xLjI5NAogICAgICAgIEwyNTcsMzU3LjVjMCwwLTEzLjU4NC04LjcwNy0yNy4yNS0xMC41Yy0xMy42NjgtMS43OTMtMjEuMDQyLDMtNDYuNSwyLjVjLTI0LjA3My0wLjQ3My03MS4yNS0xMi43NS05My4zMzMtNDUuNzUKICAgICAgICBTNjkuOTE3LDI1MS4yNSw2OS45MTcsMjUxLjI1eiIvPgo8L3N2Zz4K" width="512" height="512" filter="url(#black)" /> <image transform="translate(0 0) translate(-9 -2) scale(1, 1)" id="iconred" href="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iNTEycHgiCiAgICAgaGVpZ2h0PSI1MTJweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGZpbGw9IiMwMDAwMDAiIGQ9Ik0xMjUuNjY3LDEyMi45MTdjMCwwLDI4LDMzLjA4Myw4OS4yNSwzNC4zMzNjNjEuMjUxLDEuMjUsOTUuOTE3LTM3LjkxNywxMzAuOTE3LTMzLjMzM3M2Myw0My4zMzMsNzcuNzUsNTAuMTY3TDMzMyw0MjUuNzUKICAgICAgICBjMCwwLTEuODMzLDEuMzM0LTExLDQuNjY3cy0xMS4zMzMsNC4zMzMtMTEuMzMzLDQuMzMzbDQwLjI1LTEyMi45MTdjMCwwLTM4Ljc1LTMyLjY4Ny03My43NS0zNQogICAgICAgIGMtMzUuMDAxLTIuMzEzLTUwLjkxNywyMy43NS0xMTAuMDgzLDEzLjc1QzEwNy45MTcsMjgwLjU4Myw2OS41LDI0My41LDY5LjUsMjQzLjVzLTEuNDE1LTIxLjA2NywxNC41LTU5LjgzMwogICAgICAgIEM5OS45MTQsMTQ0LjkwMiwxMjUuNjY3LDEyMi45MTcsMTI1LjY2NywxMjIuOTE3eiIvPgo8L3N2Zz4K" width="512" height="512" filter="url(#red)" />
</g> <image transform="translate(0 0) translate(-9 -2) scale(1, 1)" id="iconblack" href="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iNTEycHgiCiAgICAgaGVpZ2h0PSI1MTJweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGZpbGw9IiMwMDAwMDAiIGQ9Ik02OS45MTcsMjUxLjI1YzAsMCw0MS4wODQsMzguNDE2LDEwMi40MTcsNDYuMDgzYzYxLjMzMiw3LjY2Nyw2Ny4wMzktMTQuNDkxLDEwMC45MTYtMTQuMjUKICAgICAgICBjMjEuNTQ4LDAuMTUzLDI5LjMzNCw5LjU4NCwyOS4zMzQsOS41ODRsLTUzLjUwNiwxNDkuNjdjMCwwLTQuMTgtMC4wNDQtMTAuMDkyLTAuNjkyYy01LjkxMS0wLjY0OC05LjU0MS0xLjI5NC05LjU0MS0xLjI5NAogICAgICAgIEwyNTcsMzU3LjVjMCwwLTEzLjU4NC04LjcwNy0yNy4yNS0xMC41Yy0xMy42NjgtMS43OTMtMjEuMDQyLDMtNDYuNSwyLjVjLTI0LjA3My0wLjQ3My03MS4yNS0xMi43NS05My4zMzMtNDUuNzUKICAgICAgICBTNjkuOTE3LDI1MS4yNSw2OS45MTcsMjUxLjI1eiIvPgo8L3N2Zz4K" width="512" height="512" filter="url(#black)" />
<text><textPath id="uppertext" startOffset="50%" href="#upper">ANTIFASCHISTISCHE</textPath></text> </g>
<text><textPath id="lowertext" startOffset="50%" href="#lower">AKTION</textPath></text> <text><textPath id="uppertext" startOffset="50%" href="#upper">ANTIFASCHISTISCHE</textPath></text>
<text><textPath id="lowertext" startOffset="50%" href="#lower">AKTION</textPath></text>
</g>
</svg> </svg>
<form> <form>
<label for="input-text-upper">Upper text</label> <label for="input-text-upper">Upper text</label>
@ -80,11 +85,15 @@
<input type="checkbox" id="input-check-lock-scale" name="lock-scale" /> <input type="checkbox" id="input-check-lock-scale" name="lock-scale" />
<label for="input-check-lock-scale">Same scale for red and black</label> <label for="input-check-lock-scale">Same scale for red and black</label>
</div> </div>
<input type="button" id="input-button-download" value="Download SVG" /> <div>
<input type="button" id="input-button-download" value="Download SVG" />
<input type="button" id="input-button-download-png" value="Download PNG" />
</div>
<label for="input-file-import-svg">Import downloaded SVG</label> <label for="input-file-import-svg">Import downloaded SVG</label>
<input type="file" id="input-file-import-svg" name="import-svg" accept="image/svg+xml" /> <input type="file" id="input-file-import-svg" name="import-svg" accept="image/svg+xml" />
</form> </form>
<a id="download" download="antifa.svg" filename="antifa.svg"></a> <a id="download" download="antifa.svg" filename="antifa.svg"></a>
<a id="download-png" download="antifa.png" filename="antifa.png"></a>
<script> <script>
let doc = document.getElementById('svg'); let doc = document.getElementById('svg');
let inputTextUpper = document.getElementById("input-text-upper"); let inputTextUpper = document.getElementById("input-text-upper");
@ -101,6 +110,7 @@
let inputCheckLockScale = document.getElementById("input-check-lock-scale"); let inputCheckLockScale = document.getElementById("input-check-lock-scale");
let inputRangeBleed = document.getElementById("input-range-bleed"); let inputRangeBleed = document.getElementById("input-range-bleed");
let inputButtonDownload = document.getElementById("input-button-download"); let inputButtonDownload = document.getElementById("input-button-download");
let inputButtonDownloadPng = document.getElementById("input-button-download-png");
let inputFileImportSvg = document.getElementById("input-file-import-svg"); let inputFileImportSvg = document.getElementById("input-file-import-svg");
inputTextUpper.oninput = (ev) => { inputTextUpper.oninput = (ev) => {
doc.getElementById("uppertext").textContent = inputTextUpper.value; doc.getElementById("uppertext").textContent = inputTextUpper.value;
@ -209,7 +219,43 @@
let a = document.getElementById('download'); let a = document.getElementById('download');
a.setAttribute('href', 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(serialized)); a.setAttribute('href', 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(serialized));
a.click(); a.click();
} };
inputButtonDownloadPng.onclick = (ev) => {
let imgSize = parseInt(prompt("Enter image size (e.g. 2048)", "2048"));
let svgRoot = doc.getElementById("svgroot");
if (Number.isNaN(imgSize)) {
return;
}
doc.getElementById("bleed").style.stroke = 'black';
doc.width.baseVal.value = imgSize;
doc.height.baseVal.value = imgSize;
doc.viewBox.baseVal.width = imgSize;
doc.viewBox.baseVal.height = imgSize;
svgRoot.transform.baseVal[0].matrix.a = imgSize/500;
svgRoot.transform.baseVal[0].matrix.d = imgSize/500;
let serialized = new XMLSerializer().serializeToString(doc);
doc.getElementById("bleed").style.stroke = '#ff00ff';
svgRoot.transform.baseVal[0].matrix.a = 1;
svgRoot.transform.baseVal[0].matrix.d = 1;
doc.viewBox.baseVal.width = 500;
doc.viewBox.baseVal.height = 500;
doc.width.baseVal.value = 500;
doc.height.baseVal.value = 500;
let canvas = document.createElement('canvas');
canvas.width = imgSize;
canvas.height = imgSize;
let ctx = canvas.getContext("2d");
let image = new Image();
image.onload = () => {
ctx.drawImage(image, 0, 0);
let a = document.getElementById('download-png');
a.setAttribute('href', canvas.toDataURL());
a.click();
};
image.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(serialized);
};
inputFileImportSvg.onchange = (ev) => { inputFileImportSvg.onchange = (ev) => {
let file = ev.target.files[0]; let file = ev.target.files[0];
let reader = new FileReader(); let reader = new FileReader();