Charts with D3

This blog will give the basics of creating a pie-chart using D3.js. New to D3? No worries. I  will try to give you a brief understanding of D3 too.

So, what is  D3?

D3–Data-Driven Documents is a JavaScript library for producing dynamic and interactive data visualizations in web browsers using widely implemented SVG, HTML5, and CSS standards.

D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.
---D3.JS

First of all we have to download its library from https://d3js.org/  or we can use the cdn  <script src="https://d3js.org/d3.v4.min.js"></script> .

After including the library or using cdn , we can create the charts very easily .If you have ever researched high performance and deeply customizable charts, then for sure you have come across to D3 charts. The D3 chart is a huge library and there are a number of posts to implement them. You can be creative without limits.

Time to draw!

Create a simple index.html file, write the code in it, and open with the browser:

<html>
  <head>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <style>
      .pie {
        margin: 20px;
      }

      svg {
        float: left;
      }

      .legend {
        float: left;
        font-family: "Verdana";
        font-size: 0.7em;
      }

      .pie text {
        font-family: "Verdana";
        fill: #000;
      }

      .pie .name-text {
        font-size: 0.8em;
      }

      .pie .value-text {
        font-size: 3em;
      }
    </style>
  </head>
  <body>
    <div id="chart"></div>
    <script>
      var data = [
        { name: "Hemant", value: 72 },
        { name: "Digvijay", value: 74 },
        { name: "Jatin", value: 52 },
        { name: "Bhaiya", value: 75 },
        { name: "B L", value: 33 }
      ];

      var text = "";
      var width = 200;
      var height = 200;
      var thickness = 40;
      var duration = 750;
      var padding = 10;
      var opacity = 0.8;
      var opacityHover = 1;
      var otherOpacityOnHover = 0.8;
      var tooltipMargin = 13;
      var chart = "#chart";

      var radius = Math.min(width - padding, height - padding) / 2;
      var color = d3.scaleOrdinal(d3.schemeCategory10);

      var svg = d3
        .select(chart)
        .append("svg")
        .attr("class", "pie")
        .attr("width", width)
        .attr("height", height);

      var g = svg
        .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

      var arc = d3
        .arc()
        .innerRadius(0)
        .outerRadius(radius);

      var pie = d3
        .pie()
        .value(function(d) {
          return d.value;
        })
        .sort(null);

      var path = g
        .selectAll("path")
        .data(pie(data))
        .enter()
        .append("g")
        .append("path")
        .attr("d", arc)
        .attr("fill", (d, i) => color(i))
        .style("opacity", opacity)
        .style("stroke", "white")
        .on("mouseover", function(d) {
          d3.selectAll("path").style("opacity", otherOpacityOnHover);
          d3.select(this).style("opacity", opacityHover);

          let g = d3
            .select("svg")
            .style("cursor", "pointer")
            .append("g")
            .attr("class", "tooltip")
            .style("opacity", 0);

          g.append("text")
            .attr("class", "name-text")
            .text(`${d.data.name} (${d.data.value})`)
            .attr("text-anchor", "middle");

          let text = g.select("text");
          let bbox = text.node().getBBox();
          let padding = 2;
          g.insert("rect", "text")
            .attr("x", bbox.x - padding)
            .attr("y", bbox.y - padding)
            .attr("width", bbox.width + padding * 2)
            .attr("height", bbox.height + padding * 2)
            .style("fill", "white")
            .style("opacity", 0.75);
        })
        .on("mousemove", function(d) {
          let mousePosition = d3.mouse(this);
          let x = mousePosition[0] + width / 2;
          let y = mousePosition[1] + height / 2 - tooltipMargin;

          let text = d3.select(".tooltip text");
          let bbox = text.node().getBBox();
          if (x - bbox.width / 2 < 0) {
            x = bbox.width / 2;
          } else if (width - x - bbox.width / 2 < 0) {
            x = width - bbox.width / 2;
          }

          if (y - bbox.height / 2 < 0) {
            y = bbox.height + tooltipMargin * 2;
          } else if (height - y - bbox.height / 2 < 0) {
            y = height - bbox.height / 2;
          }

          d3.select(".tooltip")
            .style("opacity", 1)
            .attr("transform", `translate(${x}, ${y})`);
        })
        .on("mouseout", function(d) {
          d3.select("svg")
            .style("cursor", "none")
            .select(".tooltip")
            .remove();
          d3.selectAll("path").style("opacity", opacity);
        })
        .on("touchstart", function(d) {
          d3.select("svg").style("cursor", "none");
        })
        .each(function(d, i) {
          this._current = i;
        });

      let legend = d3
        .select("#chart")
        .append("div")
        .attr("class", "legend")
        .style("margin-top", "30px");

      let keys = legend
        .selectAll(".key")
        .data(data)
        .enter()
        .append("div")
        .attr("class", "key")
        .style("display", "flex")
        .style("align-items", "center")
        .style("margin-right", "20px");

      keys
        .append("div")
        .attr("class", "symbol")
        .style("height", "10px")
        .style("width", "10px")
        .style("margin", "5px 5px")
        .style("background-color", (d, i) => color(i));

      keys
        .append("div")
        .attr("class", "name")
        .text(d => `${d.name} (${d.value})`);

      keys.exit().remove();
    </script>
  </body>
</html>

and this code will give something like this...wowww

I have also created a demo, you can find it here...

Pi Chart With D3–Data-Driven Documents

Conclusion

D3 has right set of tools that makes the connection between data and graphics easy. While these are very basic examples of what D3 and D3Pie can accomplish together, I hope this post has given you the tools and the vision to get started. I would also like to note that while this post focused on pie charts, this is a very limited view of what D3 can accomplish. Here are some amazing examples of what D3 can do. I chose pies because I am working on a project that requires them, but also because they are an easy way to get introduced to the world of D3.

Hope this was helpful.

Like this article? Follow @hemantjava on Twitter