0

I am trying to download a graph that I created with D3.js to a png (any other format would do though), very much unsuccessfully.

I am trying to create a data-url and then pass it to a function which should allow me to download it.

Like so:

First I want to create a function to create data-urls:

function svgDataURL(argument) {
         var svgAsXML = (new XMLSerializer).serializeToString(argument.node());
         return "data:image/svg+xml," + encodeURIComponent(svgAsXML);
       }

Next I am saving my url with my svg as argument in a varaiable:

var dataURL = svgDataURL(svg)
 console.log(dataURL)

when debugging this outputs the following: data:image/svg+xml,%3Cg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20transform%3D%22translate(100%2C20)%22%3E%3Crect%20class%3D%22bar%22%20width%3D%225.244670050761421%22%20y%3D%22394.44444444444446%22%20height%3D%2250%22%20fill%3D%22%23348496%22%2F%3E%3Crect%20class%3D%22bar%22%20width%3D%22526.3857868020305%22%20y%3D%22338.8888888888889%22%20height%3D%2250%22%20fill%3D%22%23348496%22%2F%3E%3Crect%20class%3D%22bar%22%20width%3D%2257.3502538071066%22%20y%3D%22283.3333333333333%22%20height%3D%2250%22%20fill%3D%22%23348496%22%2F%3E%3Crect%20class%3D%22bar%22%20width%3D%22840%22%20y%3D%22227.77777777777777%22%20height%3D%2250%22%20fill%3D%22%23348496%22%2F%3E%3Crect%20class%3D%22bar%22%20width%3D%225.116751269035533%22%20y%3D%22172.22222222222223%22%20height%3D%2250%22%20fill%3D%22%23348496%22%2F%3E%3Crect%20class%3D%22bar%22%20width%3D%2256.96649746192893%22%20y%3D%22116.66666666666666%22%20height%3D%2250%22%20fill%3D%22%23348496%22%2F%3E%3Crect%20class%3D%22bar%22%20width%3D%2260.079187817258884%22%20y%3D%2261.1111111111111%22%20height%3D%2250%22%20fill%3D%22%23348496%22%2F%3E%3Crect%20class%3D%22bar%22%20width%3D%2229.932994923857866%22%20y%3D%225.555555555555543%22%20height%3D%2250%22%20fill%3D%22%23348496%22%2F%3E%3Crect%20class%3D%22bar%22%20width%3D%2257.3502538071066%22%20y%3D%22172.22222222222223%22%20height%3D%2250%22%20fill%3D%22%23348496%22%2F%3E%3Cg%20transform%3D%22translate(0%2C450)%22%20fill%3D%22none%22%20font-size%3D%2210%22%20font-family%3D%22sans-serif%22%20text-anchor%3D%22middle%22%3E%3Cpath%20class%3D%22domain%22%20stroke%3D%22currentColor%22%20d%3D%22M0.5%2C6V0.5H840.5V6%22%2F%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(0.5%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E0%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(85.77918781725889%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E2%2C000%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(171.05837563451777%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E4%2C000%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(256.33756345177665%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E6%2C000%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(341.61675126903555%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E8%2C000%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(426.8959390862944%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E10%2C000%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(512.1751269035533%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E12%2C000%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(597.4543147208122%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E14%2C000%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(682.7335025380711%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E16%2C000%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(768.0126903553299%2C0)%22%3E%3Cline%20stroke%3D%22currentColor%22%20y2%3D%226%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20y%3D%229%22%20dy%3D%220.71em%22%3E18%2C000%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3Cg%20fill%3D%22none%22%20font-size%3D%2210%22%20font-family%3D%22sans-serif%22%20text-anchor%3D%22end%22%3E%3Cpath%20class%3D%22domain%22%20stroke%3D%22currentColor%22%20d%3D%22M-6%2C450.5H0.5V0.5H-6%22%2F%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(0%2C419.44444444444446)%22%3E%3Cline%20stroke%3D%22currentColor%22%20x2%3D%22-6%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20x%3D%22-9%22%20dy%3D%220.32em%22%3EBuilding1%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(0%2C363.8888888888889)%22%3E%3Cline%20stroke%3D%22currentColor%22%20x2%3D%22-6%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20x%3D%22-9%22%20dy%3D%220.32em%22%3EBuilding2%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(0%2C308.3333333333333)%22%3E%3Cline%20stroke%3D%22currentColor%22%20x2%3D%22-6%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20x%3D%22-9%22%20dy%3D%220.32em%22%3EBuilding3%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(0%2C252.77777777777777)%22%3E%3Cline%20stroke%3D%22currentColor%22%20x2%3D%22-6%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20x%3D%22-9%22%20dy%3D%220.32em%22%3ETradeCenter%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(0%2C197.22222222222223)%22%3E%3Cline%20stroke%3D%22currentColor%22%20x2%3D%22-6%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20x%3D%22-9%22%20dy%3D%220.32em%22%3EBuilding13%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(0%2C141.66666666666666)%22%3E%3Cline%20stroke%3D%22currentColor%22%20x2%3D%22-6%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20x%3D%22-9%22%20dy%3D%220.32em%22%3EBuilding8%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(0%2C86.1111111111111)%22%3E%3Cline%20stroke%3D%22currentColor%22%20x2%3D%22-6%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20x%3D%22-9%22%20dy%3D%220.32em%22%3EBuilding7%3C%2Ftext%3E%3C%2Fg%3E%3Cg%20class%3D%22tick%22%20opacity%3D%221%22%20transform%3D%22translate(0%2C30.555555555555543)%22%3E%3Cline%20stroke%3D%22currentColor%22%20x2%3D%22-6%22%2F%3E%3Ctext%20fill%3D%22currentColor%22%20x%3D%22-9%22%20dy%3D%220.32em%22%3EBuilding6%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fg%3E

I am assuming that this is the data link to my svg I want to create. But hey, it looks kinda long and wrong. So maybe I am already going the wrong way here.

finally I call my download function and pass my URL

 function download(){
      var dl = document.createElement("a");
      document.body.appendChild(dl);
      dl.setAttribute("href", dataURL);
      dl.setAttribute("download", "graph.svg");
      dl.click();
    }

Ok fail, it doesn't work. When I open the link or click on my download link I get an empty page.

Has anyone an idea where I go wrong? Any help is very much appreciated.

Here is my graph btw:


var data = build
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 100},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

// set the ranges
var y = d3.scaleBand()
          .range([height, 0])
          .padding(0.1);

var x = d3.scaleLinear()
          .range([0, width]);

// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select(".svg-net-area").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform",
          "translate(" + margin.left + "," + margin.top + ")");

  // format the data
  data.forEach(function(d) {
    d.buildings__net_leased_area = +d.buildings__net_leased_area;
  });

  // Scale the range of the data in the domains
  x.domain([0, d3.max(data, function(d){ return d.buildings__net_leased_area; })])
  y.domain(data.map(function(d) { return d.buildings__name; }));
  //y.domain([0, d3.max(data, function(d) { return d.buildings__net_leased_area; })]);

  // append the rectangles for the bar chart
  svg.selectAll(".bar")
      .data(data)
    .enter().append("rect")
      .attr("class", "bar")
      //.attr("x", function(d) { return x(d.buildings__net_leased_area); })
      .attr("width", function(d) {return x(d.buildings__net_leased_area); } )
      .attr("y", function(d) { return y(d.buildings__name); })
      .attr("height", y.bandwidth())
      .attr("fill", "#348496");

  // add the x Axis
  svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

  // add the y Axis
  svg.append("g")
      .call(d3.axisLeft(y));
Micromegas
  • 1,499
  • 2
  • 20
  • 49
  • Are you including XML declaration and name spaces? I think the [`Blob` approach](https://stackoverflow.com/a/38019175/2831353) tends to be easier. – mdml Jun 28 '19 at 00:37
  • ehm... I don't know tbh.... I will read up on this Blob approach and will let you know. Thanks a lot! – Micromegas Jul 01 '19 at 07:08

0 Answers0