将垂直堆叠条转换为水平堆叠条D3.js v4

时间:2018-04-03 07:49:13

标签: javascript html css json d3.js

我在Google上找到了一个垂直堆栈条形图示例 - http://bl.ocks.org/juan-cb/43f10523858abf6053ae 我想在水平堆积条形图中转换它。我做了改变,但有些事情是错的。图表不正确。我认为所有的栏都是重叠的。

请帮我解决这个问题。代码被复制。

<!DOCTYPE html>
<meta charset="utf-8">
<style>
    body {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        width: 960px;
        height: 500px;
        position: relative;
    }
    svg {
        width: 100%;
        height: 100%;
        position: center;
    }
    text{
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    }
    .toolTip {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        position: absolute;
        display: none;
        width: auto;
        height: auto;
        background: none repeat scroll 0 0 white;
        border: 0 none;
        border-radius: 8px 8px 8px 8px;
        box-shadow: -3px 3px 15px #888888;
        color: black;
        font: 12px sans-serif;
        padding: 5px;
        text-align: center;
    }
    .legend {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        font-size: 60%;
    }
    text {
        font: 10px sans-serif;
    }
    .axis text {
        font: 10px sans-serif;
    }
    .axis path{
        fill: none;
        stroke: #000;
    }
    .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
    }
    .x.axis path {
        display: none;
    }
</style>
<body>
<div  class="barGraph" id='stacked-bar'></div>
<script src="http://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.7.0/d3-legend.min.js"></script>
<script>
function wrap(text, width) {
    text.each(function() {
        var text = d3.select(this),
                words = text.text().split(/\s+/).reverse(),
                word,
                line = [],
                lineNumber = 0,
                lineHeight = 1.1, // ems
                y = text.attr("y"),
                dy = parseFloat(text.attr("dy")),
                tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
        while (word = words.pop()) {
            line.push(word);
            tspan.text(line.join(" "));
            if (tspan.node().getComputedTextLength() > width) {
                line.pop();
                tspan.text(line.join(" "));
                line = [word];
                tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
            }
        }
    });
}
init();
function init(){
   var dataset =  [{
"goodRating": 27,
"avgRating": 21,
"badRating": 16,
"rooms": "0.01"
},
  {
"goodRating": 26,
"avgRating": 22,
"badRating": 31,
"rooms": "0.02"
},
  {
"goodRating": 100,
"avgRating": 0,
"badRating": 0,
"rooms": "1"
}];
   var groupSpacing = 6;
    var margin = {top: 10, right: 10, bottom: 60, left: 100},
        width = 1000 - margin.left - margin.right,
        height = 400 - margin.top - margin.bottom;

      var y = d3.scaleBand()
            .range([height, 0]);
    var x = d3.scaleLinear()
            .range([0, width], .1,.3);

  //  var colorRange = d3.scale.category20();
    var color = d3.scaleOrdinal(d3.schemeCategory20);
    var     xAxis = d3.axisBottom(x).tickFormat(dataset.rooms),
            yAxis =  d3.axisLeft(y);
    var svg = d3.select("#stacked-bar").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var divTooltip = d3.select("body").append("div").attr("class", "toolTip");
    color.domain(d3.keys(dataset[0]).filter(function(key) { return key !== "rooms"; }));
    dataset.forEach(function(d) {
        var y0 = 0;
        var y1 = 0;
        d.values = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
        d.total = d.values[d.values.length - 1].y1;
    });
    y.domain(dataset.map(function(d) { return d.rooms; }));
    x.domain([0, d3.max(dataset, function(d) { return d.total; })]);
    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", ".5em")
              .attr("transform", "rotate(-65)");

    svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
            .append("text")
            .attr("transform", "rotate(-90)")
            .attr("y", 9)
            .attr("dy", ".71em")
            .style("text-anchor", "end")
            .text("Satisfaction %");
    var bar = svg.selectAll(".rooms")
            .data(dataset)
            .enter().append("g")
            .attr("class", "g")
            .attr("transform", function(d) { return "translate(" + y(d.rooms) + ",0)"; });
    svg.selectAll(".x.axis .tick text")
            .call(wrap, y.bandwidth());

    var bar_enter = bar.selectAll("rect")
    .data(function(d) { return d.values; })
    .enter();

    bar_enter.append("rect")
        .attr("height", y.bandwidth())
        .attr("x", function(d) { return x(d.y1); })
        .attr("width", function(d) { return x(d.y1) - x(d.y0) })
        .style("fill", function(d) { return color(d.name); });

    bar_enter.append("text")
        .text(function(d) { return d3.format(".2s")(d.y1-d.y0)+"%"; })
        .attr("x", function(d) { return x(d.y1)+(x(d.y0) - x(d.y1))/2; })
        .attr("y", y.bandwidth()/3)
        .style("fill", '#ffffff');

    bar.on("mousemove", function(d){
                divTooltip.style("left", d3.event.pageX+10+"px");
                divTooltip.style("top", d3.event.pageY-25+"px");
                divTooltip.style("display", "inline-block");
                var elements = document.querySelectorAll(':hover');
                l = elements.length
                l = l-1
                element = elements[l].__data__
                value = element.y1 - element.y0
                divTooltip.html("Room No : "+(d.rooms)+"<br>"+element.name+" : "+value+"%");
            });
    bar.on("mouseout", function(d){
                divTooltip.style("display", "none");
            });

}   
</script>
</body>

此致 Pinki Sharma

1 个答案:

答案 0 :(得分:1)

一些小事丢失/不正确:

  1. 包含条形图的组(stack path --local-bin)被错误地转换(我猜你在从垂直堆叠变为水平时错过了这一点),即下一行

    <g>

    从左侧转换条形组,y位置为0,因此重叠。我已将此改为:

    .attr("transform", function(d) { return "translate(" + y(d.rooms) + ",0)"; });
    
  2. the rects&#39; x 值已从.attr("transform", function(d) { return "translate(0, " + y(d.rooms) + ")"; }); 更改为x(d.y1)(可能是拼写错误)

    x(d.y0)
  3. scaleBand()缺少轴填充。我已添加(请查看docs以获取更多信息)

    bar_enter.append("rect")
    .attr("height", y.bandwidth())
    .attr("x", function(d) { return x(d.y0); })
    
  4. 重置边距以适应SVG尺寸:

    var y = d3.scaleBand()
      .rangeRound([height, 0]).padding(0.1);
    
  5. 结合上述所有内容,这里是您的代码集的一个分支:

    HORIZONTAL STACKED BAR CHART DEMO

    希望这有帮助。