如何在D3.js的堆叠栏中为每个文本标签添加背景?

时间:2018-07-04 15:25:44

标签: javascript d3.js svg nvd3.js

我尝试了不同的方法来在每个栏中提供文本标签的背景,以使其更加可见。但是我无法为堆栈条中的每个文本标签添加背景,也无法将每个条的总数添加为背景,因此我想将其附加到每个堆栈条上方,作为[总计:250]。

在下图中,您可以看到灰色矩形区域,我尝试将其设置为文本背景,但失败了。我是D3.js的新手,真的很难实现它。请帮我解决这个问题。

<html>
<head>
  <script src="https://d3js.org/d3.v3.min.js" type="text/javascript"></script>
  <style>
    .textRect {
      fill: white;
      stroke: none;
    }
    
    text {
      font-family: Helvetica, Arial, sans-serif;
      font-weight: bold;
      font-size: 12px;
    }
  </style>
</head>
<body style="width: 98%; background-color: white">
  <div id="ashu" style="width: 700px; height:400px; padding-top: 50px;"></div>
  <script>
    var data = [{
      "health": "JAN",
      "val1": 1,
      "val2": 67,
      "val3": 13,
      "val4": 15
    }, {
      "health": "FEB",
      "val1": 60,
      "val2": 9,
      "val3": 20,
      "val4": 5
    }, {
      "health": "MAR",
      "val1": 40,
      "val2": 22,
      "val3": 21,
      "val4": 99
    }, {
      "health": "APR",
      "val1": 60,
      "val2": 1,
      "val3": 99,
      "val4": 90
    }, {
      "health": "MAY",
      "val1": 2,
      "val2": 27,
      "val3": 43,
      "val4": 82
    }, {
      "health": "JUN",
      "val1": 17,
      "val2": 52,
      "val3": 79,
      "val4": 9
    }, {
      "health": "JUL",
      "val1": 37,
      "val2": 24,
      "val3": 35,
      "val4": 51
    }, {
      "health": "AUG",
      "val1": 16,
      "val2": 17,
      "val3": 53,
      "val4": 38
    }, {
      "health": "SEP",
      "val1": 15,
      "val2": 32,
      "val3": 5,
      "val4": 31
    }];
    let xData = d3.keys(data[0]);
    const yData = xData.shift();
    var div = d3.select("body").append("div")
      .attr("class", "tooltip")
      .style("opacity", 0);

    var margin = {
        top: 20,
        right: 50,
        bottom: 30,
        left: 50
      },
      width = 400,
      height = 300,
      padding = 100;

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

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

    var color = d3.scale.category10();

    var xAxis = d3.svg.axis().scale(x).orient("bottom");
    var y_axis = d3.svg.axis().scale(y).orient("left").ticks(6).innerTickSize(-width)
      .tickPadding(10);

    var svg = d3.select("#ashu").append("svg").attr("width",
      "100%").attr("height",
      "100%").append("g").attr(
      "transform",
      "translate(" + margin.left + "," + margin.top + ")");

    var dataIntermediate = xData.map(function(c) {
      return data.map(function(d, yData) {
        return {
          x: d[Object.keys(d)[0]],
          y: d[c]
        };
      });
    });
    var chu = 0;
    var totals = d3.nest()
      .key(function(d) {
        return d.health;
      })
      .rollup(function(d) {
        return d3.sum(d, function(g) {

          return g.val1 + g["val2"] + g.val3 + g.val4;
        });
      })
      .entries(data);

    var dataStackLayout = d3.layout.stack()(dataIntermediate);

    x.domain(dataStackLayout[0].map(function(d) {
      return d.x;
    }));
    var total = 0;
    var maximumY = d3.max(dataStackLayout[dataStackLayout.length - 1], function(d) {
      return (d.y + d.y0);
    });
    y.domain([0, maximumY]).nice();

    var layer1 = svg.selectAll(".stack1").data(dataStackLayout).enter()
      .append("g").attr("class", "stack1").style("fill",
        function(d, i) {
          return color(i);
        });

    layer1.selectAll("rect")
      .data(function(d) {
        return d;
      })
      .enter()
      .append("rect")
      .attr("x", function(d) {
        return x(d.x);
      })
      .attr("y", function(d) {
        return y(d.y + d.y0);
      })
      .attr("height", function(d) {
        return y(d.y0) - y(d.y + d.y0);
      })
      .attr("width", x.rangeBand());

    var layer2 = svg.selectAll(".stack2").data(dataStackLayout).enter()
      .append("g")
      .attr("class", "stack2")
      .style("fill", "black");

    layer2.selectAll("rect")
      .data(function(d) {
        return d;
      })
      .enter()
      .append("rect")
      .attr("class", "textRect")

      .attr("x", function(d, i) {
        return x(d.x) + (x.rangeBand()) / 2 - (this.getBBox().width / 2);
      })
      .attr("y", function(d) {
        return y(d.y0 + (d.y / 2)) - (this.getBBox().height / 2);
      }).attr("height", function(d) {
        return d.y0 / 2 - (this.getBBox().width / 2);
      })
      .attr("width", function(d) {
        return d.y0 / 2 - (this.getBBox().height / 2);
      })
      .style("opacity", "0.6")
      .style("fill", "grey");

    var textLabel = layer2.selectAll("text")
      .data(function(d) {
        return d;
      })
      .enter()
      .append("text")
      .text(function(d) {
        return d.y;
      })
      .attr("x", function(d, i) {
        return x(d.x) + (x.rangeBand()) / 2;
      })
      .attr("y", function(d) {
        return y(d.y0 + (d.y / 2));
      })
      .attr("dy", "0.35em")
      .attr("text-anchor", "middle")
      .style("fill", "white");

    /*    var bbox =  textLabel.each(function() {
           return this.getBBox();// get bounding box of text field and store it in texts array
       });
    	console.log(bbox);
    	var paddingLeftRight = 18; // adjust the padding values depending on font and font size
        var paddingTopBottom = 5;
    	
       var rectLabel =  layer2.selectAll("rect")
       .data(function(d) {
           return d;
         })
         .enter()
         .append("rect")
    	.attr("class", "textRect")
        .attr("x", function(d) { d.x.x - d.x.width/2 - paddingLeftRight/2; })
        .attr("y", function(d) { d.y.y - d.y.height + paddingTopBottom/2; })
        .attr("width", function(d) { return d.y.width + paddingLeftRight; })
        .attr("height", function(d) { return d.y.height + paddingTopBottom; }).style("fill", "#ccc")
        .style("fill-opacity", ".3")
        .style("stroke", "#666")
        .style("stroke-width", "1.5px");
       
     */

    svg.append("g").attr("class", "axis").attr("transform",
      "translate(0," + height + ")").call(xAxis);

    svg.append("g").attr("class", "y axis").attr("transform", "translate(0,0)").call(y_axis);

    var legend = svg.selectAll(".legend")
      .data(color.domain().slice())
      .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) {
        return "translate(0," + Math.abs((i - 8) * 20) + ")";
      });

    legend.append("rect")
      .attr("x", width + 10)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", color);

    legend.append("text")
      .attr("class", "legendText")
      .attr("x", width + 32)
      .attr("y", 10)
      .attr("dy", ".35em")
      .style("text-anchor", "start")
      .text(function(d, i) {
        return xData[i];
      });
  </script>
</body>
</html>

0 个答案:

没有答案