Example of Mixing Pie Charts with Typical HTML Layout and Formatting Constructs

594 views
Skip to first unread message

Guerino1

unread,
Mar 16, 2012, 9:31:07 PM3/16/12
to d3...@googlegroups.com
Hi,

I've been working on creating an example that shows how to usefully mix things like Pie Charts in with typical HTML layout and formatting constructs (see working code below for example) so that users of D3 can tap into its power for typical day-to-day business use.  The example also shows a possible standard representation for passing data into a pie chart generator (based on the d3.csv parse string format).  NOTE: To make it easy, the example includes inline CSS styles, making it a bit longer than it needs to be.

I started with Mike Bostock's "Pie Multiples with Nesting" (http://bl.ocks.org/1305337) example.  (Thanks Mike, for the example and your help. Both have been useful.)

As you can see from the example, the pies use Mike's original mechanism for overlaying Labels with respective Arcs and also places the name of the Data Set in the center of the Pie.  While it looks very slick, in normal day-to-day use this won't scale well because the names of the Labels and of the Data Sets can become significantly longer than those Mike used in his example and, therefore, they won't cleanly "fit" into the limited Arc spaces.  The result would be missing or overwritten Label and Data Set names (messy).  As a result, I'd like to achieve some next steps to extend things a but I'm hitting a bit of a wall.  I was hoping the community might be able to either help me with ideas to solve some problems or point me to other examples that might help...

1) I'd like to place the labels in a linear table "to the right" of their corresponding Pie Chart.
2) I'd like to place a color coded symbol, like a small circle, a small square, or a small diamond in front of each label, that matches the corresponding Arc in the pie it belongs to.
3) I'd like to be able to pass in "html links" and make the Labels in the table "linkable".
4) I'd like to animate each Arc of the pie, such that if I mouseover the Arc "OR" mouseover the Label in the key, the pie Arc grows/detaches from the master Pie.
5) I'd like to make the Arcs, themselves, "html linkable," so that on mouseclick (like the corresponding label) it will take you to the appropriate URL.

A working "graphael" example looks something like: http://g.raphaeljs.com/piechart2.html

NOTE: I'm trying to make my "drawPie" function as flexible as possible by allowing key arguments to be passed into the functions at call time, so that the function acts like a highly reusable library function. (Later, I'd like to do the same with Bar Charts, Line Charts, etc.)

When done, I'd like to contribute all the code back to the community as an example and possibly as the foundation for a very reusable D3 charting library.

Any thoughts or help with any of the above is greatly appreciated.  

Thanks,

Frank


--------------------- CODE --------------------------------
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html  xmlns="http://www.w3.org/1999/xhtml"
       xml:lang="en-US"
       lang="en-US">
  <head profile="http://www.w3.org/2005/10/profile">
    <title>IF4IT Sample Charts Web Page</title>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
    <meta name="Description" content="This page tries to mix charts with html formatting and layout constructs." />
    <meta http-equiv="pragma" content="no-cache" />
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="expires" content="-l" />

    <!-- <script type="text/javascript" src="../LIBS/D3/d3.js"></script> -->
    <script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.4.5"></script>

    <script type="text/javascript">

      // This example lays out multiple pie charts and comes from the source
      // located at: http://bl.ocks.org/1305337

      var dataSet1 = [
        {"setName": "Data Set 1", "label": "Label 1", "count": "25"},
        {"setName": "Data Set 1", "label": "Label 2", "count": "10"},
        {"setName": "Data Set 1", "label": "Label 3", "count": "2"},
        {"setName": "Data Set 1", "label": "Label 4", "count": "45"},
        {"setName": "Data Set 1", "label": "Label 5", "count": "15"},
        {"setName": "Data Set 1", "label": "Label 6", "count": "85"}
      ];

      var dataSet2 = [
        {"setName": "Data Set 2", "label": "Label 7", "count": "15"},
        {"setName": "Data Set 2", "label": "Label 8", "count": "13"},
        {"setName": "Data Set 2", "label": "Label 9", "count": "29"},
        {"setName": "Data Set 2", "label": "Label 10", "count": "45"},
        {"setName": "Data Set 2", "label": "Label 11", "count": "25"},
        {"setName": "Data Set 2", "label": "Label 12", "count": "25"}
      ];

      var dataSet3 = [
        {"setName": "Data Set 3", "label": "Label 13", "count": "35"},
        {"setName": "Data Set 3", "label": "Label 14", "count": "20"},
        {"setName": "Data Set 3", "label": "Label 15", "count": "12"},
        {"setName": "Data Set 3", "label": "Label 16", "count": "25"},
        {"setName": "Data Set 3", "label": "Label 17", "count": "17"},
        {"setName": "Data Set 3", "label": "Label 18", "count": "15"}
      ];

      function drawPie(dataSet, selectString, colors, margin, outerRadius, innerRadius ) {

	// dataSet => Input Data for the pie chart, itself.
	// selectString => String that allows you to pass in
	//           a D3 select string.
	// colors => String to set color scale.  Values can be...
	//           => "colorScale10"
	//           => "colorScale20"
	//           => "colorScale20b"
	//           => "colorScale20c"
	// margin => Integer margin offset value.
	// outerRadius => Integer outer radius value.
	// innerRadius => Integer inner radius value.

	// Color Scale Handling...
        var colorScale = d3.scale.category20c();
        switch (colors)
        {
          case "colorScale10":
            colorScale = d3.scale.category10();
            break;
          case "colorScale20":
            colorScale = d3.scale.category20();
            break;
          case "colorScale20b":
            colorScale = d3.scale.category20b();
            break;
          case "colorScale20c":
            colorScale = d3.scale.category20c();
            break;
          default:
            colorScale = d3.scale.category20c();
        };

	// Define a pie layout: the pie angle encodes the count of dataSet.
	// Since our data is in the form of a post-parsed CSV string, the
	// counts are Strings which we coerce to Numbers.
        var pie = d3.layout.pie()
            .value(function(d) { return +d.count; })
            .sort(function(a, b) { return b.count - a.count; });

	// Define an arc generator. Note the inner radius is specified
	// here. The layout is not specified here.
        var arc = d3.svg.arc()
            .innerRadius(innerRadius)
            .outerRadius(outerRadius);

        // Nest the label data by originating dataSet. Our data has the counts per
        // dataSet and label, but we want to group counts by dataSet.
        var dataSets = d3.nest()
            .key(function(d) { return d.setName; })
            .entries(dataSet);

        // Insert an svg element (with margin) for each label in our dataSet.
        // A child g element translates the setName to the pie center.
        var svg = d3.selectAll(selectString).selectAll('svg')
            .data(dataSets)
            .enter().append("div") // http://code.google.com/p/chromium/issues/detail?id=98951
            .style("width", (outerRadius + margin) * 2 + "px")
            .style("height", (outerRadius + margin) * 2 + "px")
            .append("svg:svg")
            .attr("width", (outerRadius + margin) * 2)
            .attr("height", (outerRadius + margin) * 2)
            .append("svg:g")
            .attr("transform", "translate(" + (outerRadius + margin) + "," + (outerRadius + margin) + ")");

        // Add a label for the dataSet. The `key` comes from the nest operator.
        svg.append("svg:text")
            .attr("dy", ".35em")
            .attr("text-anchor", "middle")
            .text(function(d) { return d.key; });

        // Pass the nested per-dataSet values to the pie layout. The layout computes
        // the angles for each arc. Another g element will hold the arc and its label.
        var g = svg.selectAll("g")
            .data(function(d) { return pie(d.values); })
            .enter().append("svg:g");

        // Add a colored arc path, with a mouseover title showing the count.
        g.append("svg:path")
            .attr("d", arc)
            .style("fill", function(d) { return colorScale(d.data.label); })
            .append("svg:title")
            .text(function(d) { return d.data.label + ": " + d.data.count; });

        // Add a label to the larger arcs, translated to the arc centroid and rotated.
        g.filter(function(d) { return d.endAngle - d.startAngle > .2; }).append("svg:text")
            .attr("dy", ".35em")
            .attr("text-anchor", "middle")
            .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")"; })
            .text(function(d) { return d.data.label; });

        // Computes the label angle of an arc, converting from radians to degrees.
        function angle(d) {
          var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
          return a > 90 ? a - 180 : a;
        }

      };

    </script>

    <style type="text/css">
      svg {
        font: 10px sans-serif;
        display: block;
      }
    </style>



    <STYLE type="text/css">
      div.div_Header {
	width: 100%;
	border:2px solid White;
	border-radius:7px;
	background: WhiteSmoke;
	font: bold 14px Arial;
	font-family:Arial, Helvetica, sans-serif;
	color:WhiteSmoke;
	text-align:center;
      }
      h1.h1_BodyHeader {
	text-align:center;
	font: bold 1.5em Arial;
      }
      h2.h2_LeftMenuHeader {
	text-align:center;
	font: bold 1.2em Arial;
      }
      table.table_Header {
	width: 100%;
	text-align:center;
      }
      td.td_HeaderLeft {
	text-align:left;
      }
      td.td_HeaderRight {
	text-align:right;
      }
      div.div_Menu {
	width: 100%;
	border:2px solid White;
	border-radius:7px;
	background: MidnightBlue;
	font: bold 14px Arial;
	font-family:Arial, Helvetica, sans-serif;
	color:White;
	text-align:center;
      }
      p.p_Left {
	font-family:Arial, Helvetica, sans-serif;
	color:Black;
	font: normal 14px Arial;
      }
      table.table_Body {
	width: 100%;
	height: 100%;
	padding: 0;
      }
      td.td_BodyLeft {
	width: 250px;
	height: 100%;
	padding: 0;
      }
      li.li_LeftMenu {
	text-align:left;
	font: normal 14px Arial;
      }
      a.a_LeftMenuNoUnderLine {
	text-decoration:  none;
      }
      div.div_Body {
	height: 100%;
	width: 100%;
	position: relative;
	border:2px solid White;
	border-radius:7px;
	background: WhiteSmoke;
	font: bold 14px Arial;
	font-family:Arial, Helvetica, sans-serif;
	color:Black;
	text-align:center;
      }
      div.div_Footer {
	width: 100%;
	border:2px solid White;
	border-radius:7px;
	background: MidnightBlue;
	font: bold 14px Arial;
	font-family:Arial, Helvetica, sans-serif;
	color:White;
	text-align:center;
      }
      p.p_if4itMessage {
	width: 100%;
	background: White;
	font: bold .75em Arial;
	font-family:Arial, Helvetica, sans-serif;
	color:GoldenRod;
	text-align:center;
      }
      .menuButton{
        background-color: MidnightBlue;
      }
      .menuButton li{
	height: 100%;
	list-style: none;
	display: inline;
      }
      .menuButton li a{
	height: 100%;
	padding: 3px 0.5em;
	text-decoration: none;
	color: White;
	background-color: MidnightBlue;
	border: 2px solid MidnightBlue;
      }
      .menuButton li a:hover{
	height: 100%;
	color: MidnightBlue;
	background-color: White;
	border-style: outset;
	background-color: White;
      }
      .menuButton li a:active{
        height: 100%;
        border-style: inset;
        color: MidnightBlue;
        background-color: White;
      }
      .menuButton li a.disabled{
        height: 100%;
        padding: 3px 0.5em;
        text-decoration: none;
        color: MidnightBlue;
        background-color: White;
        border: 2px solid MidnightBlue;
        border-style: inset;
        border-color: White;
      }
    </STYLE>
    <STYLE type="text/css">
      div.div_RootBody {
	position: relative;
	border:2px solid White;
	border-radius:7px;
	background: WhiteSmoke;
	font: normal 14px Arial;
	font-family:Arial, Helvetica, sans-serif;
	color:Black;
	padding: 0px 1em;
	text-align:left;
      }
    </STYLE>
    <!--[if gt IE 7]>
      <style>body { overflow-y:scroll; } </style>
    <![endif]-->
  </head>

  <body>

    <p id="dateString"></p>

      <div>
	<h1 style="text-align:center; font: bold 1.7em Arial;"><a href="http://www.if4it.com"><a href="http://www.if4it.com">The International Foundation for Information Technology (IF4IT)</a><br>Mockup Site Header</a></h1>
      </div>

      <div class="div_Menu">
        <ul class="menuButton">
          <li><a href="./index.html">HOME</a></li>
          <li><a href="./MasterCatalog.html">CATALOG</a></li>
          <li><a href="./Support.html">SUPPORT</a></li>
          <li><a href="./Help.html">HELP</a></li>
        </ul>
      </div>
      <table class="table_Body">
        <tr>
          <td class="td_BodyLeft">
            <div class="div_Body">
              <h2 class="h2_LeftMenuHeader">Sample Left Menu Links</h2>
              <ul>
                <li class="li_LeftMenu"><a class="a_LeftMenuNoUnderLine" href="http://www.if4it.com">IF4IT Home</a></li>
                <li class="li_LeftMenu"><a class="a_LeftMenuNoUnderLine" href="http://www.if4it.com/disciplines.html">IF4IT Disciplines</a></li>
                <li class="li_LeftMenu"><a class="a_LeftMenuNoUnderLine" href="http://www.if4it.com/glossary.html">IF4IT Glossary</a></li>
                <li class="li_LeftMenu"><a class="a_LeftMenuNoUnderLine" href="http://www.if4it.com/taxonomy.html">IF4IT Taxonomies</a></li>
              </ul>
	      <p class="p_Left">This is dummy paragraph 1 text that would go in this section of the page.</p>
	      <p class="p_Left">This is dummy paragraph 2 text that would go in this section of the page.</p>
	      <p class="p_Left">This is dummy paragraph 3 text that would go in this section of the page.</p>
	      <p class="p_Left">This is dummy paragraph 4 text that would go in this section of the page.</p>
	      <p class="p_Left">This is dummy paragraph 5 text that would go in this section of the page.</p>
              <ul>
                <li class="li_LeftMenu"><a class="a_LeftMenuNoUnderLine" href="http://www.if4it.com">IF4IT Home</a></li>
                <li class="li_LeftMenu"><a class="a_LeftMenuNoUnderLine" href="http://www.if4it.com/disciplines.html">IF4IT Disciplines</a></li>
                <li class="li_LeftMenu"><a class="a_LeftMenuNoUnderLine" href="http://www.if4it.com/glossary.html">IF4IT Glossary</a></li>
                <li class="li_LeftMenu"><a class="a_LeftMenuNoUnderLine" href="http://www.if4it.com/taxonomy.html">IF4IT Taxonomies</a></li>
              </ul>
	      <p class="p_Left">This is dummy paragraph 1 text that would go in this section of the page.</p>
	      <p class="p_Left">This is dummy paragraph 2 text that would go in this section of the page.</p>
	      <p class="p_Left">This is dummy paragraph 3 text that would go in this section of the page.</p>
	      <p class="p_Left">This is dummy paragraph 4 text that would go in this section of the page.</p>
	      <p class="p_Left">This is dummy paragraph 5 text that would go in this section of the page.</p>
            </div>
          </td>
          <td>
            <div class="div_RootBody">
              <h1 style="text-align:center; font: bold 1.5em Arial;">IF4IT Page Body Header</h1>
            </div>
            <div class="div_RootBody">
	      <h3>Content Section: No Charts Here</h3>
	      <p>This is dummy paragraph 1 text that would go in this section of the page.</p>
	      <p>This is dummy paragraph 2 text that would go in this section of the page.</p>
            </div>
            <div class="div_RootBody" id="pie_chart_1">
              <h3>Pie Chart Number 1</h3>
              <div class="chart"></div>
            </div>
            <div class="div_RootBody" id="pie_chart_2">
              <h3>Pie Chart Number 2</h3>
              <div class="chart"></div>
            </div>
            <div class="div_RootBody">
	      <h3>Content Section: No Charts Here</h3>
	      <p>This is dummy paragraph 1 text that would go in this section of the page.</p>
	      <p>This is dummy paragraph 2 text that would go in this section of the page.</p>
            </div>
            <div class="div_RootBody" id="pie_chart_3">
              <h3>Pie Chart Number 3</h3>
              <div class="chart"></div>
            </div>
          </td>
        </tr>
      </table>

      <div class="div_Footer"><p><p>This is the IF4IT Footer Message for this web page.</p></p></div>

      <div><p class="p_if4itMessage">This Site Has Been Created and Published by The International Foundation for Information Technology (IF4IT).</p></div>

      <script type="text/javascript">
        drawPie(dataSet1, "#pie_chart_1 .chart", "colorScale20", 5, 100, 33);
        drawPie(dataSet2, "#pie_chart_2 .chart", "colorScale20b", 5, 100, 33);
        drawPie(dataSet3, "#pie_chart_3 .chart", "colorScale20c", 5, 100, 33);
      </script>

    </body>

</html>

Kai Chang

unread,
Mar 16, 2012, 9:41:04 PM3/16/12
to d3...@googlegroups.com

Frank Guerino

unread,
Mar 16, 2012, 10:15:03 PM3/16/12
to d3...@googlegroups.com
Hi Kai,

Thanks for putting it up on bl.ocks (wasn't expecting that).  If you're going to keep it there, could I ask you to please correct my name?  It's "Guerino", not "Geurino".

Thanks
Reply all
Reply to author
Forward
0 new messages