(idea)SVGをpreviewするUserScript
動機
svgをreal timeにpreviewしながら描きたい 実装
SVGの描画
いくつかある
<canvas>に書き込む
<svg>を埋め込む
<img>で表示する
<svg>と<img>を切り替えられるようにしたい
JS実行は前者でないと試せない
scrapbox等では<img>でしか表示できないので、そちらの表示環境も確認したい
実装
実験的に作ったもの
UIが安定していない
2023-01-07
11:23:37 問題なさそう
https://gyazo.com/33565cfc7089946a14745d5aeff03f66
networkが遅いと反映されるまで数十秒かかる
やはりscrapbox.Page.linesから取り出すのが一番早い
hot reloadするとどう表示されるかのテスト
開発コンソールから実行できる
code:demo.js
{
const filename = "test.svg";
const app = document.createElement("div");
const id = scrapbox.Page.lines.find((line) => {
if (!("codeBlock" in line)) return false;
return line.codeBlock.filename === filename && line.codeBlock.end;
})?.id ?? "";
document.getElementById(L${id}).insertAdjacentElement("afterend", app);
const img = document.createElement("img");
const pre = document.createElement("pre");
const code = document.createElement("code");
pre.append(code);
app.append(img, pre);
pre.hidden = true;
img.hidden = true;
let url;
let runningId = 0;
const render = async () => {
const current = runningId;
const res = await fetch(/api/code/${scrapbox.Project.name}/${scrapbox.Page.title}/test.svg);
const text = await res.text();
if (runningId !== current) return;
if (img.src) URL.revokeObjectURL(img.src);
const dom = new DOMParser().parseFromString(
text,
"image/svg+xml"
);
const error = dom.querySelector("parsererror");
// if failed to parse
if (error) {
code.textContent = error.innerHTML;
pre.hidden = false;
img.hidden = true;
return;
}
url = URL.createObjectURL(
new Blob(text, { type: "image/svg+xml" }) );
img.src = url;
pre.hidden = true;
img.hidden = false;
};
let timer;
render();
scrapbox.on("lines:changed", () => {
clearTimeout(timer);
timer = setTimeout(
() =>{
runningId++;
render();
},
100
);
});
}
code:test.svg
<g stroke-width="0.1">
<g fill="red">
<rect x="0" y="0" width="10" height="10"/>
<rect x="12" y="1" width="10" height="10"/>
</g>
<g stroke="lightgray" text-anchor="end" font-size="0.05em">
<line x1="1" y1="0" x2="1" y2="20"/>
<line x1="0" y1="1" x2="20" y2="1"/>
<text x="1" y="1" dx="-0.1" dy="-0.1">0</text>
</g>
<polygon points="0,0 0,20, 20,20, 20,0" stroke="#ccc" fill="none"/>
</g>
</svg>