在d3js中绘制折线图和条形图。问题

时间:2015-11-06 22:29:28

标签: javascript d3.js svg

我使用在线发现的各种例子来学习d3j。

我一直试图用双Y轴和X轴绘制图表。左侧的Y轴将绘制相对于X轴的图表,右侧的Y轴将针对X轴绘制线图表。条形图完全按照要求绘制,但折线图没有。 X轴是日期(2015-10-15 04:10)。以this为例。

我写的代码

var margin = {top: 50, right: 50, bottom: 100, left: 50},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%m/%d/%Y %H:%M:%S").parse;

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

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

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")

var yAxis = d3.svg.axis()
    .scale(yTxnVol)
    .orient("left")

var yAxis2 = d3.svg.axis()
    .scale(yResTime)
    .orient("right")
    .ticks(10);
var svg = d3.selectAll("body").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 + ")");

d3.csv("../res/data.csv", function(error, data) {

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

  x.domain(data.map(function(d) { return d.TYM; }));
  yTxnVol.domain([0, d3.max(data, function(d) { return d.TXN_VOL+50; })]);
  yResTime.domain([0, d3.max(data, function(d) { return d.AVRG_RESP_TIME+50; })]);

  var minDate = d3.min(data, function(d){return d.TYM});
  var maxDate = d3.max(data, function(d){ return d.TYM});
  var xScale = d3.time.scale().range([0,width]);//.domain([minDate, maxDate]);
  xScale.domain(d3.extent(data, function(d) { return new Date(d.TYM); }));

  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", "-.55em")
      .attr("transform", "rotate(-90)" );

   svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)

   svg.append("g")
      .attr("class","y axis")
      .attr("transform","translate("+width+ ", 0)")
      .call(yAxis2)

   svg.selectAll("bar")
      .data(data)
    .enter().append("rect")
      .attr("class", "yhover")
      .attr("x", function(d) { return x(d.TYM); })
      .attr("width", x.rangeBand())
      .attr("y", function(d) { return yTxnVol(d.TXN_VOL); })
      .attr("height", function(d) { return height - yTxnVol(d.TXN_VOL); })

   var line = d3.svg.line()
      .x(function(d) { return xScale(new Date(d.TYM));})
      .y(function(d) { return d.AVRG_RESP_TIME; });

   svg.append("path")
      .datum(data)
      .attr("class", "line")
      .attr("d", line);   
});

输出尝试将其设置为有意义的折线图。格式化日期时出现NaN错误。 有人可以帮助我制作一个合适的折线图吗?

csv数据样本

TYM,AVRG_RESP_TIME,TXN_VOL

2015-10-15 04:00:00,11,170

2015-10-15 04:10:00,18,220

2015-10-15 04:20:00,28,251

2015-10-15 05:00:19,19

2 个答案:

答案 0 :(得分:1)

首先,修复您的csv文件。格式不正确,逗号后不应有空格。

其次,您正在尝试为您的xAxis混合有序量表和时间刻度。这不会起作用。对于您的用例,只需坚持时间。

以下是使用解释性注释重新编写代码:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>

<body>
  <script>
    var margin = {
        top: 50,
        right: 50,
        bottom: 100,
        left: 50
      },
      width = 900 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;
      
    var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;

    // x scale should be time and only time
    var x = d3.time.scale().range([0, width]);
    var yTxnVol = d3.scale.linear().range([height, 0]);
    var yResTime = d3.scale.linear().range([height, 0]);

    var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom")

    var yAxis = d3.svg.axis()
      .scale(yTxnVol)
      .orient("left")

    var yAxis2 = d3.svg.axis()
      .scale(yResTime)
      .orient("right")
      .ticks(10);
      
    var svg = d3.selectAll("body").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 + ")");

    //d3.csv("data.csv", function(error, data) {
      
      var data = [{"TYM":"2015-10-15 04:00:00","AVRG_RESP_TIME":"12","TXN_VOL":"170"},{"TYM":"2015-10-15 04:10:00","AVRG_RESP_TIME":"18","TXN_VOL":"220"},{"TYM":"2015-10-15 04:20:00","AVRG_RESP_TIME":"28","TXN_VOL":"251"},{"TYM":"2015-10-15 05:00:00","AVRG_RESP_TIME":"19","TXN_VOL":"100"}];

      // just make TYM a date and keep it as a date
      data.forEach(function(d) {
        d.TYM = parseDate(d.TYM);
        d.AVRG_RESP_TIME = +d.AVRG_RESP_TIME;
        d.TXN_VOL = +d.TXN_VOL;
      });
      
      // get our min and max date in milliseconds
      // set a padding around our domain of 15%
      var minDate = d3.min(data, function(d){
        return d.TYM;
      }).getTime();
      var maxDate = d3.max(data, function(d){
        return d.TYM;
      }).getTime();
      var padDate = (maxDate - minDate) * .15;
      x.domain([new Date(minDate - padDate), new Date(maxDate + padDate)]);
      
      yTxnVol.domain([0, d3.max(data, function(d) {
        return d.TXN_VOL + 50;
      })]);
      
      yResTime.domain([0, d3.max(data, function(d) {
        return d.AVRG_RESP_TIME + 50;
      })]);
      
      // set an intelligent bar width
      var barWidth = (width / x.ticks().length) - 20;
      
      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", "-.55em")
        .attr("transform", "rotate(-90)");

      svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)

      svg.append("g")
        .attr("class", "y axis")
        .attr("transform", "translate(" + width + ", 0)")
        .call(yAxis2)

      svg.selectAll("bar")
        .data(data)
        .enter().append("rect")
        .attr("class", "yhover")
        .attr("x", function(d) {
          // center bar on time
          return x(d.TYM) - (barWidth / 2);
        })
        .attr("width", barWidth) 
        .attr("y", function(d) {
          return yTxnVol(d.TXN_VOL);
        })
        .attr("height", function(d) {
          return height - yTxnVol(d.TXN_VOL);
        })
        .style("fill","orange");

      var line = d3.svg.line()
        .x(function(d) {
          return x(d.TYM);
        })
        .y(function(d) {
          return d.AVRG_RESP_TIME;
        });

      svg.append("path")
        .datum(data)
        .attr("class", "line")
        .attr("d", line)
        .style("fill","none")
        .style("stroke","steelblue")
        .style("stoke-width","3px");
   // });
  </script>
</body>

</html>

答案 1 :(得分:0)

填充黑色的折线图的问题是由于css不正确。新的css属性。

.line {
  fill: none;
  stroke: darkgreen;
  stroke-width: 2.5px;
}

对于我将其格式化为(%Y-%m-%d%H:%M)格式的日期并且它有效。