d3.js v4条形图,y轴为负值

时间:2017-10-10 02:32:31

标签: javascript d3.js svg charts

我在d3.js中使用了相当多的图表,这些图表在x轴上具有负值,但我看到很少有关于y的负值的例子,我没有能够使用它们。

我正在尝试使用x轴上的日期和y轴上的相应值创建图表。

我试过通过操作以下链接中的代码来尝试这样做:

D3 v4 bar chart X axis with negative values

我的代码如下:

var margin2 = { top: 20, right: 20, bottom: 40, left: 30 };
var height2 = 650 - margin2.top - margin2.bottom;
var width2 = 900 - margin2.left - margin2.right;

// Add svg to
var svg = d3.select('#macdChart').
    append('svg').
    attr('width', width2 + margin2.left + margin2.right).
    attr('height', height2 + margin2.top + margin2.bottom).
    append('g').
    attr('transform', 'translate(' + margin2.left + ',' + margin2.top + ')');

//title
svg.append("text")
    .attr("x", (width2 / 2))
    .attr("y", 0 - (margin2.top / 3))
    .attr("text-anchor", "middle")
    .style("font-size", "16px")
    .style("text-decoration", "underline")
    .text("Title");

// X scale
var x2 = d3.scaleBand().
    range([width2, 0])
    .padding(0.1);

//y scale
var y2 = d3.scaleLinear()
    .range([height2, 0]);



var xAxis = d3.axisBottom(x2);

var yAxis = d3.axisLeft(y2).
    tickSize(6, 0);

// text label for the x axis
svg.append("text")
    .attr("transform", "translate(" + (width2 / 2) + " ," + (height2 + margin2.top + 20) + ")")
    .style("text-anchor", "middle")
    .text("X Label");


function render(data) {
    data.forEach(function (d) {
        d.Macd = +d.Macd;
        d.MacdSignal = +d.MacdSignal;
        d.MacdHistogram = +d.MacdHistogram;
    });

    x2.domain(data.map(function (d) { return d["date"]; }));
    y2.domain(d3.extent(data, function (d) { return d["MacdHistogram"]; })).nice();

    svg.selectAll('.bar').
        data(data).
        enter().append('rect').
        attr('class', function (d) {
            return "bar bar--" + (d["MacdHistogram"] < 0 ? "negative" : "positive");
        }).
        attr('x', function (d) { return x2(d["date"]); }).
        attr('y', function (d) { return y2(Math.min(0, d["MacdHistogram"])); }).
        attr('height', function (d) { return Math.abs(y2(d["MacdHistogram"]) - y2(0)); }).
        attr('width', x2.bandwidth());

    svg.append('g').
        attr('class', 'y axis').
        attr('transform', 'translate(' + width2 + ',0)').
        call(yAxis);

    var tickNegative = svg.append('g').
        attr('class', 'x axis').
        attr('transform', 'translate(0,' + y2(0) + ')').
        call(xAxis).
        selectAll('.tick').
        filter(function (d, i) { return data[i].value < 0; });

    }

产生以下内容: d3Image1

现在,如果我在y上切换范围:

    var y2 = d3.scaleLinear()
        .range([height2, 0]);

要:

    var y2 = d3.scaleLinear()
        .range([0, height2]);

我得到下面的图表,其中条形图值正确显示,但负数位于顶部,正数位于底部(正如您在y轴标签上看到的):

image2

有人可以建议如何让图表看到它究竟是如何做的,现在只是翻转所以负面是在底部吗?

1 个答案:

答案 0 :(得分:1)

而不是Math.min位置的y,请使用Math.max

.attr('y', function (d) { 
    return y2(Math.max(0, d["MacdHistogram"]))
});

原因在于,无论范围的方向如何,SVG矩形始终(除非您弄乱transform)的宽度从左到右增长,并且高度从上到下成长。

以下是使用虚假数据进行更改的演示:

var margin2 = {
  top: 20,
  right: 20,
  bottom: 20,
  left: 20
};
var height2 = 400 - margin2.top - margin2.bottom;
var width2 = 500 - margin2.left - margin2.right;

// Add svg to
var svg = d3.select('body').
append('svg').
attr('width', width2 + margin2.left + margin2.right).
attr('height', height2 + margin2.top + margin2.bottom).
append('g').
attr('transform', 'translate(' + margin2.left + ',' + margin2.top + ')');

//title
svg.append("text")
  .attr("x", (width2 / 2))
  .attr("y", 0 - (margin2.top / 3))
  .attr("text-anchor", "middle")
  .style("font-size", "16px")
  .style("text-decoration", "underline")
  .text("Title");

// X scale
var x2 = d3.scaleBand().
range([width2, 0])
  .padding(0.1);

//y scale
var y2 = d3.scaleLinear()
  .range([height2, 0]);



var xAxis = d3.axisBottom(x2);

var yAxis = d3.axisLeft(y2).
tickSize(6, 0);

// text label for the x axis
svg.append("text")
  .attr("transform", "translate(" + (width2 / 2) + " ," + (height2 + margin2.top + 20) + ")")
  .style("text-anchor", "middle")
  .text("X Label");


function render(data) {
  x2.domain(data.map(function(d) {
    return d["date"];
  }));
  y2.domain(d3.extent(data, function(d) {
    return d["MacdHistogram"];
  })).nice();

  svg.selectAll('.bar').
  data(data).
  enter().append('rect').
  attr('class', function(d) {
    return "bar bar--" + (d["MacdHistogram"] < 0 ? "negative" : "positive");
  }).
  attr('x', function(d) {
    return x2(d["date"]);
  }).
  attr('y', function(d) {
    return y2(Math.max(0, d["MacdHistogram"]));
  }).
  attr('height', function(d) {
    return Math.abs(y2(d["MacdHistogram"]) - y2(0));
  }).
  attr('width', x2.bandwidth());

  svg.append('g').
  attr('class', 'y axis').
  attr('transform', 'translate(' + width2 + ',0)').
  call(yAxis);

  var tickNegative = svg.append('g').
  attr('class', 'x axis').
  attr('transform', 'translate(0,' + y2(0) + ')').
  call(xAxis).
  selectAll('.tick').
  filter(function(d, i) {
    return data[i].value < 0;
  });
}

var data = [{
  date: 1,
  MacdHistogram: 1
}, {
  date: 2,
  MacdHistogram: -2
}, {
  date: 3,
  MacdHistogram: 8
}, {
  date: 4,
  MacdHistogram: 3
}, {
  date: 5,
  MacdHistogram: 12
}, {
  date: 6,
  MacdHistogram: -5
}, {
  date: 7,
  MacdHistogram: 1
}, {
  date: 8,
  MacdHistogram: 9
}, {
  date: 9,
  MacdHistogram: -1
}, {
  date: 10,
  MacdHistogram: 10
}, {
  date: 11,
  MacdHistogram: 7
}, {
  date: 12,
  MacdHistogram: -8
}, {
  date: 13,
  MacdHistogram: 7
}, {
  date: 14,
  MacdHistogram: -4
}, {
  date: 15,
  MacdHistogram: 1
}];

render(data)
<script src="https://d3js.org/d3.v4.min.js"></script>