Public
Edited
Nov 30, 2023
Fork of Saving SVG
Insert cell
Insert cell
import {chart} from "@d3/contours"
Insert cell
Insert cell
Insert cell
DOM.download(() => serialize(chart), undefined, "Save as SVG")
Insert cell
serialize = {
const xmlns = "http://www.w3.org/2000/xmlns/";
const xlinkns = "http://www.w3.org/1999/xlink";
const svgns = "http://www.w3.org/2000/svg";
return function serialize(svg) {
svg = svg.cloneNode(true);
const fragment = window.location.href + "#";
const walker = document.createTreeWalker(svg, NodeFilter.SHOW_ELEMENT);
while (walker.nextNode()) {
for (const attr of walker.currentNode.attributes) {
if (attr.value.includes(fragment)) {
attr.value = attr.value.replace(fragment, "#");
}
}
}
svg.setAttributeNS(xmlns, "xmlns", svgns);
svg.setAttributeNS(xmlns, "xmlns:xlink", xlinkns);
const serializer = new window.XMLSerializer;
const string = serializer.serializeToString(svg);
return new Blob([string], {type: "image/svg+xml"});
};
}
Insert cell
Insert cell
DOM.download(() => rasterize(chart), undefined, "Save as PNG")
Insert cell
serialize(chart).text()
Insert cell
canvg = import("https://cdn.skypack.dev/canvg@^4.0.0")
Insert cell
// canvg.Canvg

// const canvas = document.querySelector('canvas');
// const ctx = canvas.getContext('2d');
// const v = Canvg.fromString(ctx, '<svg width="600" height="600"><text x="50" y="50">Hello World!</text></svg>');

// // Start SVG rendering with animations and mouse handling.
// v.start();
Insert cell
function rasterize(svg) {
let resolve, reject;
const promise = new Promise((y, n) => (resolve = y, reject = n));
const image = new Image;
image.onerror = reject;
image.onload = () => {
const rect = svg.getBoundingClientRect();
const context = DOM.context2d(rect.width, rect.height);
console.log('image', image);
context.drawImage(image, 0, 0, rect.width, rect.height);
context.canvas.toBlob(resolve);
};
image.src = URL.createObjectURL(serialize(svg));
return promise;
}
Insert cell
async function rasterize_canvg(svg) {
let resolve, reject;
const promise = new Promise((y, n) => (resolve = y, reject = n));
const serialized_svg = serialize(svg);
const serialized_text = await serialized_svg.text();
// console.log('serialized_text', serialized_text)
const image = new Image;
image.onerror = reject;
image.onload = async () => {
var canvas = document.createElement("canvas");
canvas.width = svg.width.baseVal.value;
canvas.height = svg.height.baseVal.value;
const ctx = canvas.getContext('2d');
const rect = svg.getBoundingClientRect();
const context = DOM.context2d(rect.width, rect.height);
const v = canvg.Canvg.fromString(ctx, serialized_text);
await v.start()
// console.log('ready?', v.isReady())
// console.log('image', image);
// context.drawImage(image, 0, 0, rect.width, rect.height);
context.canvas.toBlob((res) => {console.log('res', res); resolve(res)});
};
image.src = URL.createObjectURL(serialize(svg));
// console.log('hello???')
// console.log('promise?', promise)
return promise;
}
Insert cell
rasterize_canvg(chart)
Insert cell
DOM.download(() => rasterize_canvg(chart), undefined, "Save as PNG")
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more