d3.js日期时间:小时未在y轴上正确显示

时间:2018-04-23 20:02:48

标签: datetime d3.js

使用d3.js v4我试图在y轴上绘制时间图。 y轴表示24小时的时钟。

数据很简单,

[{
    "start": "2016-11-14 20:00",
    "end": "2016-11-14 23:59"
  },
  {
    "start": "2016-11-16 01:00",
    "end": "2016-11-16 03:00"
  },
  {
    "start": "2016-11-15 00:00",
    "end": "2016-11-15 04:00"
  }
]

第一个对象应该从20到24进行图形化,但它从19到23进行。这表明存在一个问题,例如基于零的计数。

有没有人对我如何解决这个问题提出建议?

以下是完整的代码段

<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title>d3 datetime graph</title>
  <script src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
  <svg width="800" height="400"></svg>
  </div>
  <div id="json">
  </div>
  <!-- <script type="text/javascript" src="script.js"></script> -->
  <script type="text/javascript">
    var svg = d3.select("svg"),
      margin = {
        top: 20,
        right: 60,
        bottom: 60,
        left: 40
      },
      width = +svg.attr("width") - margin.left - margin.right,
      height = +svg.attr("height") - margin.top - margin.bottom;
    var color = ["#2C93E8", "#838690", "#F56C4E", "#A60F2B", "#648C85", "#B3F2C9", "#528C18", "#C3F25C"];


    var data = [{
        "start": "2016-11-14 20:00",
        "end": "2016-11-14 23:59"
      },
      {
        "start": "2016-11-16 01:00",
        "end": "2016-11-16 03:00"
      },
      {
        "start": "2016-11-15 00:00",
        "end": "2016-11-15 04:00"
      }
    ]

    var parseTime = d3.timeParse("%Y-%m-%d %H:%M");
    var parseDay = d3.timeParse("%e %b %Y");
    var formatDay = d3.timeFormat("%e %b %Y");
    // data.forEach(function(d) {
    //   commence = parseTime(d.start);
    //   conclude = parseTime(d.end);
    //   if (commence.getDay() != conclude.getDay()) {
    //     // a check here in case they are more than a day apart
    //     // 2016-11-04 12:00
    //
    //     morning = conclude.getFullYear() + "-" + (conclude.getMonth() + 1) + "-" + conclude.getDate() + " 00:00";
    //     console.log("morning is " + morning);
    //     data.push({
    //       "start": morning,
    //       "end": d.end
    //     })
    //     midnight = commence.getFullYear() + "-" + (commence.getMonth() + 1) + "-" + commence.getDate() + " 23:59";
    //     console.log("midnight is " + midnight);
    //     d.end = midnight;
    //     //we need to remove current object
    //     //what element in the array is it, read the 'i'
    //     //use slice to remove that element data.slice(i,1) or soemthing like that
    //   }
    // });
    console.log(JSON.stringify(data, null, 2));

    data.forEach(function(d) {
        d.start = parseTime(d.start);
        d.end = parseTime(d.end);
        d.duration = ((d.end - d.start) / (60 * 1000) / 60); // session duration in hours
        d.starttime = d.start.getHours();
        d.endtime = d.end.getHours();
        d.daily = formatDay(d.start);
        d.day = parseDay(d.daily);

        return d;
      },
      function(error, data) {
        if (error) throw error;
      });

    document.getElementById("json").innerHTML = "<h5>data.json</h5>" + "<pre>" + JSON.stringify(data, null, 2) + "</pre>";

    var x = d3.scaleTime()
      .domain(d3.extent(data, function(d) {
        return d.day; //need to round to day
      }))
      .range([0, width]);

    var y = d3.scaleLinear()
      .domain([0, 24])
      .range([height, 0]);

    var group = svg.append("g");

    group.selectAll(".bar")
      .data(data)
      .enter()
      .append("rect")
      .style("fill", "blue")
      .attr("class", "bar")
      .attr("transform", "translate(80,0)")
      .attr("x", function(d) {
        return x(d.day) + 10;
      })
      .attr("y", function(d) {
        //if ((d.endtime + d.duration) > 24) {
        // console.log("oh no:")
        // console.log("d.starttime: " + d.starttime); //2
        // console.log("y(d.starttime): " + y(d.starttime)); //293.3333
        // console.log("d.endtime: " + d.endtime); //18
        // console.log("y(d.endtime): " + y(d.endtime)); //80
        // console.log("d.duration: " + d.duration); //16
        // console.log("y(d.duration): " + y(d.duration)); //106.6666
        // console.log("height: " + height); //320
        // console.log("y(16): " + y(16)); //106.6666
        // console.log("y(24): " + y(24)); //0
        // console.log("y(0): " + y(0)); //320
        // console.log("height - y(d.duration): " + (height - y(d.duration))); //320-106.666=213.333
        //  }
        return y(d.endtime);
      })
      .attr("width", 20)
      .attr("height", function(d) {
        return height - y(d.duration);
        // return y(d.starttime);
      })
      .style("fill", function(d, i) {
        return color[i];
      });

    svg.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(100," + (height + 2) + ")")
      .call(d3.axisBottom(x).ticks(d3.timeDay.every(1)).tickFormat(d3.timeFormat("%e %b %Y")))
      // axis.ticks(d3.timeMinute.every(15));
      // .call(d3.axisBottom(x))
      .selectAll("text")
      .style("text-anchor", "end")
      .attr("dx", "-.8em")
      .attr("dy", ".15em")
      .attr("transform", "rotate(-35)");

    svg.append("g")
      .attr("class", "axis axis--y")
      .attr("transform", "translate(80,0)")
      .call(d3.axisLeft(y).ticks(24))
      .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 0)
      .attr("x", 0)
      .attr("dy", "0.71em")
      .attr("text-anchor", "end")
      .text("duration (hours)");
  </script>
</body>

</html>

由于

1 个答案:

答案 0 :(得分:1)

因此,您遇到问题的第一个栏就是基于这些数据:

{
  "start": "2016-11-14 20:00",
  "end": "2016-11-14 23:59"
},

您根据其endtime进行定位,其类似于

d.endtime = d.end.getHours();

所以,这就是问题:如果你得到23:59的小时,它是23,而不是24:JavaScript没有四舍五入到最近的小时,它只需要一小时部分。如果您想要更准确的y轴,您可以:

  • 使用不是几小时的东西,比如几分钟或几秒钟。
  • 为每个条形图创建一个时间刻度,并将其域设置为条形图时间范围之前/之后的午夜。