First working version of wasm svg->png generator

pull/17/head
Mike Lynch 2025-01-11 17:18:43 +11:00
parent daa4bbf9b3
commit 146894583b
2 changed files with 61 additions and 12 deletions

View File

@ -1,14 +1,16 @@
// adapted from the DOM.download method as per this issue:
// https://github.com/observablehq/framework/issues/906
const xmlns = "http://www.w3.org/2000/xmlns/"; const xmlns = "http://www.w3.org/2000/xmlns/";
const xlinkns = "http://www.w3.org/1999/xlink"; const xlinkns = "http://www.w3.org/1999/xlink";
const svgns = "http://www.w3.org/2000/svg"; const svgns = "http://www.w3.org/2000/svg";
// adapted from the DOM.download method as per this issue:
// https://github.com/observablehq/framework/issues/906
export function download(value, name = "untitled", label = "Save") { export function download(value, name = "untitled", label = "Save") {
console.log("in download");
const a = document.createElement("a"); const a = document.createElement("a");
const b = a.appendChild(document.createElement("button")); const b = a.appendChild(document.createElement("button"));
b.textContent = label; b.textContent = label;
@ -32,8 +34,6 @@ export function download(value, name = "untitled", label = "Save") {
b.textContent = "Saving…"; b.textContent = "Saving…";
try { try {
const object = await (typeof value === "function" ? value() : value); const object = await (typeof value === "function" ? value() : value);
console.log("svg object:");
console.log(object);
b.textContent = "Download"; b.textContent = "Download";
a.href = URL.createObjectURL(object); // eslint-disable-line require-atomic-updates a.href = URL.createObjectURL(object); // eslint-disable-line require-atomic-updates
console.log(`url = ${a.href}`); console.log(`url = ${a.href}`);
@ -48,11 +48,16 @@ export function download(value, name = "untitled", label = "Save") {
} }
export function serialize_svg(svg) { export function svg_to_string(svg) {
svg = svg.cloneNode(true); svg = svg.cloneNode(true);
svg.setAttributeNS(xmlns, "xmlns", svgns); svg.setAttributeNS(xmlns, "xmlns", svgns);
svg.setAttributeNS(xmlns, "xmlns:xlink", xlinkns); svg.setAttributeNS(xmlns, "xmlns:xlink", xlinkns);
const serializer = new window.XMLSerializer; const serializer = new window.XMLSerializer;
const string = serializer.serializeToString(svg); return serializer.serializeToString(svg);
return new Blob([string], {type: "image/svg+xml"}); }
export function svg_to_blob(svg) {
const str = svg_to_string(svg);
return new Blob([string], {type: "image/svg+xml"})
} }

View File

@ -2,6 +2,8 @@
toc: false toc: false
--- ---
<h1>poptimal</h1> <h1>poptimal</h1>
<p>v1.1.0 | by <a href="https://mikelynch.org">mike lynch</a> | <a href="https://aus.social/@mikelynch">@mikelynch@aus.social</a> | <a href="https://git.tilde.town/bombinans/poptimal">source</a></p> <p>v1.1.0 | by <a href="https://mikelynch.org">mike lynch</a> | <a href="https://aus.social/@mikelynch">@mikelynch@aus.social</a> | <a href="https://git.tilde.town/bombinans/poptimal">source</a></p>
@ -14,9 +16,13 @@ toc: false
import {RADIUS_OPTS, DotMaker} from './components/dots.js'; import {RADIUS_OPTS, DotMaker} from './components/dots.js';
import {PALETTES, DotControls} from './components/controls.js'; import {PALETTES, DotControls} from './components/controls.js';
import {download, serialize_svg} from './components/download.js'; import {download, svg_to_string, svg_to_blob} from './components/download.js';
import random from "npm:random"; import random from "npm:random";
import * as resvg from 'npm:@resvg/resvg-wasm';
await resvg.initWasm(fetch('https://unpkg.com/@resvg/resvg-wasm/index_bg.wasm'));
const CELL = 10; const CELL = 10;
const MAG = 2; const MAG = 2;
const WIDTH = 20; const WIDTH = 20;
@ -154,14 +160,52 @@ display(svg.node());
```js ```js
display(download(() => serialize_svg(svg.node()), "poptimal.svg", "Save as SVG")); display(download(() => svg_to_blob(svg.node()), "poptimal.svg", "Save as SVG"));
``` ```
</p> ```js
</div>
const png_img = document.createElement("img");
async function svg_to_png (svg) {
// The Wasm must be initialized first
const svgstr = svg_to_string(svg.node());
const opts = {
background: 'rgba(238, 235, 230, .9)',
fitTo: {
mode: 'width', // If you need to change the size
value: 400,
}
};
const resvgJS = new resvg.Resvg(svgstr, opts)
console.log(resvgJS);
const pngData = resvgJS.render(svgstr, opts) // Output PNG data, Uint8Array
console.log(`pngData = ${pngData}`);
const pngBuffer = pngData.asPng();
const pngURL = URL.createObjectURL(new Blob([pngBuffer], { type: 'image/png' }))
console.log(`url = ${pngURL}`);
png_img.src = pngURL
}
display(png_img);
const made_png = view(Inputs.button("Make PNG"));
```
```js
made_png;
console.log(made_png);
if( made_png > 0 ) {
console.log("Trying to make png");
await svg_to_png(svg);
}
```
</div> </div>