D3条形图 - 如何一起显示正/负值?

时间:2016-11-08 14:01:08

标签: javascript d3.js

我试图在D3中创建一个复制this design的条形图。这个想法是值的范围从-100到100并且彼此并排显示。比例必须保持为0-100,颜色用于表示数字是高于还是低于0.

我设法创建了一个显示正数的简单条形图,但只要添加负数,图表就会中断。以下代码用于创建x和y轴。如果x域更改为[-100,100],则会显示负值,但这样做会使图表以与原始设计过于不同的方式呈现。

  var y = d3.scaleBand()
        .range([height, 0])
        .padding(0.1);

 var x = d3.scaleLinear()
            .range([0, width]);

x.domain([0, 100])
y.domain(data.map(function(d) { return d.sentiment; }));

任何人都可以提供一些关于制作与所提供的设计类似的图表的提示/指导,如果它甚至可能的话?链接到我当前的图表可以在下面的JSFiddle中找到:

JSFiddle

非常感谢。

1 个答案:

答案 0 :(得分:4)

只需使用Math.abs()

.attr("width", function(d){
    return x(Math.abs(d.value));
})

以下是演示:

  var data = [{"sentiment":"Result","value":28},{"sentiment":"Result2","value":-56}]

  var margin = {top: 20, right: 20, bottom: 50, left: 70},
      width = 850 - margin.left - margin.right,
      height = 200 - margin.top - margin.bottom;

  var y = d3.scaleBand()
            .range([height, 0])
            .padding(0.1);

  var x = d3.scaleLinear()
            .range([0, width]);

  var svg = d3.select("#graph").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 + ")");

    data.forEach(function(d) {
      d.value = +d.value;
    });

    x.domain([0, 100])
    y.domain(data.map(function(d) { return d.sentiment; }));

    svg.selectAll(".bar")
        .data(data)
      .enter().append("rect")
        .attr("class", "bar")
        .attr("width", function(d) {return x(Math.abs(d.value)); } )
        .attr("y", function(d) { return y(d.sentiment) + 15; })
        .attr("height", y.bandwidth())
        .attr("fill", function(d) {
          if (d.value <= 0) {
            return "#FC4E5C";
          } else {
            return "#34A232";
          }
        });

    svg.append("g")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x));

    svg.append("g")
        .call(d3.axisLeft(y));

      svg.append("text")
      .attr("class", "x label")
      .attr("text-anchor", "end")
      .attr("x", width - 300)
      .attr("y", height + 40)
      .text("Sentiment (%)");
.bar {
margin-top: 50px;
  height: 30px;
}

 text {
  fill: black;
  font-size: 14px;
}

path {
  stroke: black;
}

line {
  stroke: black;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
  <div id="graph">
  </div>