Source code of plot #057 back to plot
Download full working sketch as 057.tar.gz.
Unzip, then start a local web server and load the page in a browser.
Unless otherwise noted, code published here is © Gábor L Ugray, shared under the Creative Commons
BY-NC-SA license (Attribution, Non-Commercial, Share-Alike). Files in lib/thirdparty
, and additional
libraries in the downloadable archive, are shared under their respective open-source licenses, attributed
to their authors.
let libsPending = 0;
let sketchFun;
let theSeed;
function setSketch(fun) {
if (typeof document !== 'undefined') {
document.addEventListener('DOMContentLoaded', () => {
sketchFun = fun;
if (libsPending == 0) sketchFun();
});
}
}
function scriptname() {
if (window.fxhash) return '110-flowspace-rectangles';
const d = new Date();
const dateStr = d.getFullYear() + "-" + ("0" + (d.getMonth() + 1)).slice(-2) + "-" +
("0" + d.getDate()).slice(-2) + "!" +
("0" + d.getHours()).slice(-2) + "-" + ("0" + d.getMinutes()).slice(-2);
return '110-flowspace-rectangles' + "-" + dateStr;
}
function loadLib(name) {
const script = document.createElement('script');
script.src = "lib/" + name + ".js";
script.onload = function () {
--libsPending;
if (libsPending == 0 && sketchFun) sketchFun();
};
++libsPending;
document.head.appendChild(script);
}
function init(w, h, pw, ph) {
document.title = scriptname();
paper.install(window);
paper.settings.insertItems = false;
const elmDrawing = document.getElementById("drawing");
const elmCanvasHost = document.getElementById("canvasHost");
paper.setup("paper-canvas");
paper.project.activeLayer.name = "0-base";
if (!pw) {
pw = w;
ph = h;
}
const elmCanvas = document.getElementById("paper-canvas");
const elmBGCanvas = document.getElementById("bg-canvas");
elmCanvas.width = w;
elmCanvas.height = h;
elmCanvas.style.width = "100%";
elmCanvas.style.height = "100%";
if (elmBGCanvas) {
elmBGCanvas.width = w;
elmBGCanvas.height = h;
elmBGCanvas.style.width = "100%";
elmBGCanvas.style.height = "100%";
}
sizeCanvas(elmDrawing, elmCanvasHost, w, h);
if (window.fxhash) {
window.addEventListener("resize", () => sizeCanvas(elmDrawing, elmCanvasHost, w, h));
document.addEventListener("keydown", (e) => {
if (e.code != "KeyS") return;
let elmDownload = document.getElementById("download");
if (elmDownload.href != "") {
elmDownload.click();
return;
}
let elmP = document.createElement("p");
elmP.innerHTML = "Generating plottable SVG<br><i>Hang in there... this takes long.</i>";
elmCanvasHost.append(elmP);
setTimeout(() => {
renderSvg(w, h, pw, ph);
elmP.remove();
elmDownload.click();
}, 10);
});
}
else {
const elmRender = document.getElementById("render");
elmRender.addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
elmRender.setAttribute("href", "");
setTimeout(function () {
renderSvg(w, h, pw, ph);
elmRender.style.display = "none";
document.getElementById("download").style.display = "block";
}, 50);
});
}
}
function sizeCanvas(elmDrawing, elmCanvasHost, w, h) {
if (!window.fxhash) {
const pxWidth = 600;
elmCanvasHost.style.width = pxWidth + "px";
elmCanvasHost.style.height = (pxWidth * h / w) + "px";
}
else {
// Strategy: fit to width, but if too high, then fit to height
const parentWidth = elmDrawing.clientWidth;
const parentHeight = elmDrawing.clientHeight;
let canvasHeight = parentWidth * h / w;
if (canvasHeight <= parentHeight) {
elmCanvasHost.style.width = parentWidth + "px";
elmCanvasHost.style.height = canvasHeight + "px";
}
else {
let canvasWidth = parentHeight / h * w;
elmCanvasHost.style.width = canvasWidth + "px";
elmCanvasHost.style.height = parentHeight + "px";
}
}
}
function showUpdatePlot(callback) {
const elmRender = document.getElementById("render");
const elmDownload = document.getElementById('download');
const elmUpdatePlot = document.getElementById("updatePlot");
elmUpdatePlot.style.display = "block";
elmUpdatePlot.addEventListener("click", () => {
elmDownload.style.display = "none";
elmRender.style.display = "block";
callback();
});
}
function generateSVG(w, h, pw, ph) {
const elmSvg = project.exportSVG({
asString: false,
precision: 3,
matchShapes: false,
});
elmSvg.setAttribute("width", (pw / 10) + "mm");
elmSvg.setAttribute("height", (ph / 10) + "mm");
let left = (w - pw) / 2;
let top = (h - ph) / 2;
elmSvg.setAttribute("viewBox", left + "," + top + "," + pw + "," + ph);
elmSvg.setAttribute("xmlns:sodipodi", "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd");
elmSvg.setAttribute("xmlns:inkscape", "http://www.inkscape.org/namespaces/inkscape");
let svgStr = elmSvg.outerHTML;
svgStr = svgStr.replaceAll("<path></path>", "");
svgStr = svgStr.replaceAll(/<g id="([^"]+)"/g, "$& inkscape:groupmode='layer' inkscape:label='$1'");
// <g id="0-base"
return svgStr;
}
function renderSvg(w, h, pw, ph) {
const elmRender = document.getElementById("render");
elmRender.removeAttribute("href");
setTimeout(function() {
const svgStr = generateSVG(w, h, pw, ph);
let file;
let data = [];
data.push(svgStr);
let properties = { type: 'image/svg+xml' };
try { file = new File(data, scriptname() + ".svg", properties); }
catch { file = new Blob(data, properties); }
let url = URL.createObjectURL(file);
const elmDownload = document.getElementById('download');
elmDownload.href = url;
if (window.fxhash) {
elmDownload.download = scriptname() + "-" + theSeed + ".svg";
}
else {
elmDownload.download = scriptname() + ".svg";
}
elmRender.setAttribute("href", "#");
}, 50);
}
function info(str, seed) {
if (window.fxhash) {
theSeed = seed;
console.log(str);
return;
}
document.getElementById("info").getElementsByTagName("label")[0].textContent = str;
}
function clear() {
paper.project.clear();
dbgRedraw();
}
function dbgRedraw() {
const canvas = document.getElementById("paper-canvas");
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
paper.view.draw();
}
function spin(delay = 0) {
return new Promise(resolve => {
setTimeout(resolve, delay);
});
}
export { init, showUpdatePlot, generateSVG, renderSvg, info, spin, loadLib, setSketch, clear, dbgRedraw };