Open robindemourat opened 4 years ago
definitely yes, but I'm not sure how to do that easily. I would very much like also to be able to generate social cards images on the fly for each view so that when someone shares a url, the tweet/post immediately shows the actual viz, but manet seems to break on the interface's js unfortunately :(
For the svg and png exports here is some code (tested and working in the console ;)):
/**
* Get the vis content and remove black surfaces
*/
function retrieveSVG(selector) {
// get element
const el = document.querySelector(selector);
// clone it for modifications
const svg = el.cloneNode(true);
// remove surfaces
svg.querySelectorAll('.surface').forEach(e => e.parentNode.removeChild(e))
return svg;
}
/**
* Serialize a svg to a url
*/
function svgToDataURL(svg) {
const serializer = new XMLSerializer();
let source = serializer.serializeToString(svg);
//add name spaces if needed (bit from https://stackoverflow.com/questions/23218174/how-do-i-save-export-an-svg-file-after-creating-an-svg-with-d3-js-ie-safari-an)
if(!source.match(/^<svg[^>]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){
source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
}
if(!source.match(/^<svg[^>]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){
source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
}
//add xml declaration
source = '<?xml version="1.0" standalone="no"?>\r\n' + source;
return "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(source);
}
/**
* Turn a svg element into a png data url
*/
function svgToPng(el, fileName) {
return new Promise(function(resolve, reject) {
const serializer = new XMLSerializer();
const svgString = serializer.serializeToString(el);
const canvas = document.createElement('canvas');
canvas.width = el.getAttribute('width');
canvas.height = el.getAttribute('height');
const ctx = canvas.getContext("2d");
const DOMURL = self.URL || self.webkitURL || self;
document.body.appendChild(canvas);
const img = new Image();
const svg = new Blob([svgString], {type: "image/svg+xml;charset=utf-8"});
const url = DOMURL.createObjectURL(svg);
img.onload = function() {
ctx.drawImage(img, 0, 0);
const pngURL = canvas.toDataURL("image/png");
resolve(pngURL)
document.body.removeChild(canvas)
};
img.onerror = reject;
img.src = url;
})
}
/**
* Download a svg string
*/
function download(url, fileName) {
const dl = document.createElement("a");
document.body.appendChild(dl); // This line makes it work in Firefox.
dl.setAttribute("href", url);
dl.setAttribute("download", fileName);
dl.click()
document.body.removeChild(dl)
}
/**
* Actionable function for svg export
*/
function downloadAsSVG() {
const svg = retrieveSVG('.svg svg')
const url = svgToDataURL(svg)
download(url, 'graph.svg')
}
/**
* Actionable function for png export
*/
function downloadAsPNG() {
const svg = retrieveSVG('.svg svg')
svgToPng(svg)
.then(url => {
download(url, 'test.png')
})
}
For the social cards, too bad for manet ... hard to see a way to handle all the possible permutations with another method (will think about it !).
Really cool, thanks, will try and add it! (maybe in the OpenData/Download section?)
And out of curiosity I just retried with Manet and it seems to work now! I guess I has some bad js at the time that was breaking phantom?... Will try to use it as well then!
After further experimentation and reflexion, I'm afraid there's no acceptable solution without generating the html with a different image value in the social meta unfortunately, so letting one download the image of his current view is probably the easiest
Issues to adress for image downloads:
Wouldn't it be useful to be able to export a given view in SVG/PNG (with a white/transparent background ?) for further work with other tools ?