javascriptnvd3.js

Title for keys in nvd3 multiBarChart


Is it possible to have a legend for the "key" variable in a nvd3 multibarchart?

The keys appear at the top right corner, "In progress" and "Complete" in the example below.

I mean I'd like to add a title, say "Status", to these two items. Something like:

Status
o Complete   o In progress

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <link
      href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.css"
      rel="stylesheet"
      type="text/css"
    />
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"
      charset="utf-8"
    ></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.js"></script>

    <style>
      text {
        font: 12px sans-serif;
      }
      svg {
        display: block;
      }
      html, body, #chart1, svg {
        margin: 0px;
        padding: 0px;
        height: 100%;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="chart1">
      <svg></svg>
    </div>

    <script>
      var selector = "#chart1 svg";
      var XaxisLabel = "Project";
      var YaxisLabel = "Count";
      var Data = [
        {
          key: "Complete",
          values: [
            {
              label: "Pr1",
              value: 2
            },
            {
              label: "Pr2",
              value: 2
            },
            {
              label: "Pr3",
              value: 2
            }
          ],
          color: "blue"
        },
        {
          key: "In progress",
          values: [
            {
              label: "Pr1",
              value: 2
            },
            {
              label: "Pr2",
              value: 1
            },
            {
              label: "Pr3",
              value: 1
            }
          ],
          color: "red"
        }
      ];

      nv.addGraph(function () {
        var chart = nv.models
          .multiBarChart()
          .x(function (d) {
            return d.label;
          })
          .y(function (d) {
            return d.value;
          })
          .duration(1300)
          .margin({ bottom: 100, left: 70 })
          .rotateLabels(0)
          .groupSpacing(0.1);

        chart.reduceXTicks(false).staggerLabels(false);

        chart.xAxis
          .axisLabel(XaxisLabel)
          .axisLabelDistance(35);

        chart.yAxis
          .axisLabel(YaxisLabel)
          .axisLabelDistance(-5)
          .showMaxMin(false);

        d3.select(selector).datum(Data).call(chart);

        nv.utils.windowResize(chart.update);

        return chart;
      });
    </script>
  </body>
</html>


Solution

  • Within the addGraph function we could append text to the left of the legend:

    d3.select('.nv-legend g')
              .append("g")
              .attr("transform", "translate(-40,5)")
              .append("text")
              .attr("dy", ".32em")
              .attr("dx", 8)
              .attr("class", "nv-legend-text")
              .attr("text-anchor", "end")
              .text("Status:"); 
    

    Within the original code that would be:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8" />
        <link
          href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.css"
          rel="stylesheet"
          type="text/css"
        />
        <script
          src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"
          charset="utf-8"
        ></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.6/nv.d3.min.js"></script>
    
        <style>
          text {
            font: 12px sans-serif;
          }
          svg {
            display: block;
          }
          html, body, #chart1, svg {
            margin: 0px;
            padding: 0px;
            height: 100%;
            width: 100%;
          }
        </style>
      </head>
      <body>
        <div id="chart1">
          <svg></svg>
        </div>
    
        <script>
          var selector = "#chart1 svg";
          var XaxisLabel = "Project";
          var YaxisLabel = "Count";
          var Data = [
            {
              key: "Complete",
              values: [
                {
                  label: "Pr1",
                  value: 2
                },
                {
                  label: "Pr2",
                  value: 2
                },
                {
                  label: "Pr3",
                  value: 2
                }
              ],
              color: "blue"
            },
            {
              key: "In progress",
              values: [
                {
                  label: "Pr1",
                  value: 2
                },
                {
                  label: "Pr2",
                  value: 1
                },
                {
                  label: "Pr3",
                  value: 1
                }
              ],
              color: "red"
            }
          ];
    
          nv.addGraph(function () {
            var chart = nv.models
              .multiBarChart()
              .x(function (d) {
                return d.label;
              })
              .y(function (d) {
                return d.value;
              })
              .duration(1300)
              .margin({ bottom: 100, left: 70 })
              .rotateLabels(0)
              .groupSpacing(0.1);
    
            chart.reduceXTicks(false).staggerLabels(false);
    
            chart.xAxis
              .axisLabel(XaxisLabel)
              .axisLabelDistance(35);
    
            chart.yAxis
              .axisLabel(YaxisLabel)
              .axisLabelDistance(-5)
              .showMaxMin(false);
    
            d3.select(selector).datum(Data).call(chart);
    
            nv.utils.windowResize(chart.update);
            
            d3.select('.nv-legend g')
              .append("g")
              .attr("transform", "translate(-40,5)")
              .append("text")
              .attr("dy", ".32em")
              .attr("dx", 8)
              .attr("class", "nv-legend-text")
              .attr("text-anchor", "end")
              .text("Status:"); 
    
            return chart;
          });
    
        </script>
      </body>
    </html>

    That works correctly when resizing the browser.

    You can change the -40 to make it nearer/further from the legend.