Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3.js version 5 chart to PDF

I'm currently using d3.js version 5 and was wondering if there is an actual way for me to export my charts to PDF? For example in the screenshot provided below, there is a button for me to use or an option for me to export that specific chart to PDF F

like image 685
Elijah Leis Avatar asked May 14 '20 14:05

Elijah Leis


People also ask

What is d3js used for?

D3. js is a JavaScript library used to manipulate documents based on data. It uses HTML, CSS, and SVG to create visual representations of data which can be viewed on any modern browser. It also provides some awesome features for interactions and animations.

Is D3 js still used?

The JavaScript ecosystem has completely changed during this time, in terms of libraries, best practices and even language features. Nevertheless, D3 is still here. And it's more popular than ever.


1 Answers

You can use PDFKIT library to achieve this, this snippet is inspired by the example they provided in the live demo, I just extended it by adding the D3.js example along javascript to retrieve the HTML text.

Update: I added custom implementation to allow custom file name for the downloaded PDF, basically I create <a> tag, append it to body, then assign download attribute to it, and the href attribute contains the blob object URL we created.

NOTE: this will not work in the snippet since its a sandbox, it should work fine in your local machine and production.


const svgToPdfExample = (svg) => {
  const doc = new window.PDFDocument();
  const chunks = [];
  const stream = doc.pipe({
    // writable stream implementation
    write: (chunk) => chunks.push(chunk),
    end: () => {
      const pdfBlob = new Blob(chunks, {
        type: "application/octet-stream",
      });
      var blobUrl = URL.createObjectURL(pdfBlob);
      //window.open(`${blobUrl}?customfilename.pdf`);
      
      /* custom file name download */
      const a = document.createElement("a");
      document.body.appendChild(a);
      a.style = "display: none";
      a.href = blobUrl;
      a.download = "test.pdf"; // <---- 👈 file name
      a.click();
      window.URL.revokeObjectURL(url);
    },
    // readable streaaam stub iplementation
    on: (event, action) => {},
    once: (...args) => {},
    emit: (...args) => {},
  });

  window.SVGtoPDF(doc, svg, 0, 0);

  doc.end();
};

document.getElementById("download").addEventListener("click", function () {
  const svgElement = document.getElementById("svg");
  svgToPdfExample(svgElement.innerHTML);
});

var margin = { top: 20, right: 20, bottom: 70, left: 40 },
  width = 900 - margin.left - margin.right,
  height = 300 - margin.top - margin.bottom;

// Parse the date / time
var parseDate = d3.time.format("%Y-%m").parse;

var x = d3.scale.ordinal().rangeRoundBands([0, width], 0.05);

var y = d3.scale.linear().range([height, 0]);

var xAxis = d3.svg
  .axis()
  .scale(x)
  .orient("bottom")
  .tickFormat(d3.time.format("%Y-%m"));

var yAxis = d3.svg.axis().scale(y).orient("left").ticks(10);

var svg = d3
  .select("body")
  .append("svg")
  .attr("id", "svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.csv(
  "https://gist.githubusercontent.com/d3noob/8952219/raw/5017886e4fe22af2a7e06e20cf381bcf09cdc6db/bar-data.csv",
  function (error, data) {
    data.forEach(function (d) {
      d.date = parseDate(d.date);
      d.value = +d.value;
    });

    x.domain(
      data.map(function (d) {
        return d.date;
      })
    );
    y.domain([
      0,
      d3.max(data, function (d) {
        return d.value;
      }),
    ]);

    svg
      .append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis)
      .selectAll("text")
      .style("text-anchor", "end")
      .attr("dx", "-.8em")
      .attr("dy", "-.55em")
      .attr("transform", "rotate(-90)");

    svg
      .append("g")
      .attr("class", "y axis")
      .call(yAxis)
      .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Value ($)");

    svg
      .selectAll("bar")
      .data(data)
      .enter()
      .append("rect")
      .style("fill", "steelblue")
      .attr("x", function (d) {
        return x(d.date);
      })
      .attr("width", x.rangeBand())
      .attr("y", function (d) {
        return y(d.value);
      })
      .attr("height", function (d) {
        return height - y(d.value);
      });
  }
);
.axis {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}
<!DOCTYPE html>
<meta charset="utf-8">
<head>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/js/pdfkit.standalone.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/source.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

<button id="download">Donwload SVG as PDF</button>
</body>
like image 176
ROOT Avatar answered Sep 19 '22 13:09

ROOT