Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

image exports #29

Open
robindemourat opened this issue Apr 1, 2020 · 5 comments
Open

image exports #29

robindemourat opened this issue Apr 1, 2020 · 5 comments
Labels
feature New feature or request
Projects

Comments

@robindemourat
Copy link

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 ?

@boogheta
Copy link
Owner

boogheta commented Apr 1, 2020

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 :(

@boogheta boogheta added the feature New feature or request label Apr 1, 2020
@robindemourat
Copy link
Author

robindemourat commented Apr 2, 2020

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 !).

@boogheta
Copy link
Owner

boogheta commented Apr 2, 2020

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!

@boogheta
Copy link
Owner

boogheta commented Apr 2, 2020

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

@boogheta boogheta added this to V3 in Roadmap Apr 3, 2020
@boogheta boogheta moved this from V3 to In progress in Roadmap Apr 3, 2020
@boogheta boogheta moved this from In progress to V3 in Roadmap Apr 3, 2020
@boogheta boogheta moved this from V3 to In progress in Roadmap Apr 6, 2020
@boogheta
Copy link
Owner

boogheta commented Apr 6, 2020

Issues to adress for image downloads:

  • what about the background ? Default transparent is probably not the best option for social sharing
  • remove hover rects
  • add title with info on current config
  • add Y axis title with info on current config
  • add places legend
  • add a source text with a logo and link to the app?

@boogheta boogheta moved this from In progress to Backlog in Roadmap Apr 6, 2020
@boogheta boogheta moved this from Backlog to V4 in Roadmap Apr 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
Roadmap
  
V4
Development

No branches or pull requests

2 participants