【问题标题】:Plotting time on y-axis and date on x-axis d3.js在 y 轴上绘制时间,在 x 轴上绘制日期 d3.js
【发布时间】:2017-03-03 03:51:35
【问题描述】:

Image of the chart

var cValue = function(d) {
    return d.date;
  },
  color = d3.scale.category10();

var data = [{
    "date": "30-Dec-16",
    "time": "Mon Dec 30 2016 16:29:23 GMT+0530 (India Standard Time)",
    "close": "30"
  },
  {
    "date": "27-Jan-17",
    "time": "Mon Jan 27 2017 11:29:23 GMT+0530 (India Standard Time)",
    "close": "20"
  },
  {
    "date": "1-Feb-17",
    "time": "Mon Feb 1 2017 15:29:23 GMT+0530 (India Standard Time)",
    "close": "10"
  },
  {
    "date": "10-Feb-17",
    "time": "Mon Feb 10 2017 21:29:23 GMT+0530 (India Standard Time)",
    "close": "10"
  }
];
var dateformat = d3.time.format("%H:%M").parse;
var parseDate = d3.time.format("%d-%b-%y").parse;
data.forEach(function(d) {
  d.date = parseDate(d.date);
  //d.time=formattedDateTime(d.time);
  //d3.time.format('%H %M')(new Date(d.time));
  d.time = d3.time.format('%H:%M')(new Date(d.time));


  console.log("asubstring" + d.time);
  //d.time = parseTime(d.time);
  console.log(d.time);
});



var width = 1660;
height = 700;
padding = 100;
var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 40
  },
  width = 1260 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;
// create an svg container
var vis = d3.select("body").
append("svg:svg")
  .attr("width", width)
  .attr("height", height);
// add the graph canvas to the body of the webpage
vis = d3.select("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 + ")");
// define the y scale  (vertical)


var mindate = new Date(2012, 0, 1),
  maxdate = new Date(2012, 0, 31);


var yScale = d3.time.scale()
  .domain([new Date(), new Date()])
  .nice(d3.time.day) // values between 0 and 100
  .range([height - padding, padding]); // map these to the chart height, less padding.  
//REMEMBER: y axis range has the bigger number first because the y value of zero is at the top of chart and increases as you go down.

// define the x scale (horizontal)
var mindate = new Date(2016, 11, 1),
  maxdate = new Date();

var xScale = d3.time.scale()
  .domain([mindate, maxdate]) // values between for month of january
  .range([padding, width - padding * 2]); // map these the the chart width = total width minus padding at both sides


// define the y axis

var yValue = function(d) {
  return d.time;
}; // data -> value
var yMap = function(d) {
  return yValue(d);
};
var yAxis = d3.svg.axis()
  .orient("left")
  .scale(yScale).ticks(24).tickFormat(d3.time.format("%H:%M"));

// define the x axis
// setup x 
var xValue = function(d) {
  return d.date;
}; // data -> value
// value -> display
xMap = function(d) {
  return xScale(xValue(d));
};
var xAxis = d3.svg.axis()
  .orient("bottom")
  .scale(xScale).tickFormat(d3.time.format("%Y-%m-%d"));

// draw y axis with labels and move in from the size by the amount of padding
vis.append("g")
  .attr("transform", "translate(" + padding + ",0)")
  .call(yAxis);

// draw x axis with labels and move to the bottom of the chart area
vis.append("g")
  .attr("class", "xaxis") // give it a class so it can be used to select only xaxis labels  below
  .attr("transform", "translate(0," + (height - padding) + ")")
  .call(xAxis);

// draw dots
vis.selectAll(".dot")
  .data(data)
  .enter().append("circle")
  .attr("class", "dot")
  .attr("r", 3.5)
  .attr("cx", xMap)
  .attr("cy", yMap)
  .style("fill", function(d) {
    return color(cValue(d));
  })
  .on("mouseover", function(d) {
    tooltip.transition()
      .duration(200)
      .style("opacity", .9);
    tooltip.html(d["Cereal Name"] + "<br/> (" + xValue(d) +
        ", " + yValue(d) + ")")
      .style("left", (d3.event.pageX + 5) + "px")
      .style("top", (d3.event.pageY - 28) + "px");
  })
  .on("mouseout", function(d) {
    tooltip.transition()
      .duration(500)
      .style("opacity", 0);
  });

// now rotate text on x axis
// solution based on idea here: https://groups.google.com/forum/?fromgroups#!topic/d3-js/heOBPQF3sAY
// first move the text left so no longer centered on the tick
// then rotate up to get 45 degrees.
vis.selectAll(".xaxis text") // select all the text elements for the xaxis
  .attr("transform", function(d) {
    return "translate(" + this.getBBox().height + "," + this.getBBox().height;
  });
// draw legend
var legend = vis.selectAll(".legend")
  .data(color.domain())
  .enter().append("g")
  .attr("class", "legend")
  .attr("transform", function(d, i) {
    return "translate(0," + i * 20 + ")";
  });

// draw legend colored rectangles
legend.append("rect")
  .attr("x", width - 18)
  .attr("width", 18)
  .attr("height", 18)
  .style("fill", color);

// draw legend text
legend.append("text")
  .attr("x", width - 24)
  .attr("y", 9)
  .attr("dy", ".35em")
  .style("text-anchor", "end")
  .text(function(d) {
    return d;
  });
body {
  font: 11px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.dot {
  stroke: #000;
}

.tooltip {
  position: absolute;
  width: 200px;
  height: 28px;
  pointer-events: none;
}
<html>

<head>
  <title>D3 Axis Example</title>
  <script src="http://d3js.org/d3.v2.js"></script>
</head>
<style>

</style>

<body>

  <script>
  </script>

</body>

</html>

嗨, 我正在尝试在图表上绘制点,x 轴上是日期,y 轴上是时间。 x y 轴标签正确呈现,但不知何故,这些图没有花时间,只绘制了日期。我无法找出我做错了什么。 我附上了图表的图像以及我的代码 sn-p。 任何帮助将不胜感激

【问题讨论】:

    标签: javascript d3.js charts timeserieschart


    【解决方案1】:

    为了使用d3.time.scale 绘制绝对时间值,我们需要将时间值转换为Date 对象。我已将绝对时间值映射到带有今天日期的Date

        var today = new Date()
        var time = new Date(d.time)
        today.setHours(time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds())
        d.time = today;
    

    我将 y 轴的域更改为从今天开始到今天结束。

    var start_of_day = new Date()
    start_of_day.setHours(0,0,0,0)
    var end_of_day = new Date()
    end_of_day.setHours(23,59,59,999)
    
    var yScale = d3.time.scale()
      .domain([start_of_day, end_of_day])
      .nice(d3.time.day)
      .range([height - padding, padding])
    

    我在yMap函数中使用d3时间刻度将日期对象转换为svg y坐标:

    var yMap = function(d) {
      return yScale(yValue(d));
    };
    

    这是工作代码 sn-p:

    var cValue = function(d) {
        return d.date;
      },
      color = d3.scale.category10();
    
    var data = [{
        "date": "30-Dec-16",
        "time": "Mon Dec 30 2016 16:29:23 GMT+0530 (India Standard Time)",
        "close": "30"
      },
      {
        "date": "27-Jan-17",
        "time": "Mon Jan 27 2017 11:29:23 GMT+0530 (India Standard Time)",
        "close": "20"
      },
      {
        "date": "1-Feb-17",
        "time": "Mon Feb 1 2017 15:29:23 GMT+0530 (India Standard Time)",
        "close": "10"
      },
      {
        "date": "10-Feb-17",
        "time": "Mon Feb 10 2017 21:29:23 GMT+0530 (India Standard Time)",
        "close": "10"
      }
    ];
    var dateformat = d3.time.format("%H:%M").parse;
    var parseDate = d3.time.format("%d-%b-%y").parse;
    data.forEach(function(d) {
      d.date = parseDate(d.date);
      //d.time=formattedDateTime(d.time);
      //d3.time.format('%H %M')(new Date(d.time));
     	var today = new Date()
      var time = new Date(d.time)
      today.setHours(time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds())
      d.time = today;
    });
    
    
    
    var width = 1660;
    height = 700;
    padding = 100;
    var margin = {
        top: 20,
        right: 20,
        bottom: 30,
        left: 40
      },
      width = 1260 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;
    // create an svg container
    var vis = d3.select("body").
    append("svg:svg")
      .attr("width", width)
      .attr("height", height);
    // add the graph canvas to the body of the webpage
    vis = d3.select("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 + ")");
    // define the y scale  (vertical)
    
    
    var mindate = new Date(2012, 0, 1),
      maxdate = new Date(2012, 0, 31);
    
    var start_of_day = new Date()
    start_of_day.setHours(0,0,0,0)
    var end_of_day = new Date()
    end_of_day.setHours(23,59,59,999)
    
    var yScale = d3.time.scale()
      .domain([start_of_day, end_of_day])
      .nice(d3.time.day) // values between 0 and 100
      .range([height - padding, padding]); // map these to the chart height, less padding.  
    //REMEMBER: y axis range has the bigger number first because the y value of zero is at the top of chart and increases as you go down.
    
    // define the x scale (horizontal)
    var mindate = new Date(2016, 11, 1),
      maxdate = new Date();
    
    var xScale = d3.time.scale()
      .domain([mindate, maxdate]) // values between for month of january
      .range([padding, width - padding * 2]); // map these the the chart width = total width minus padding at both sides
    
    
    // define the y axis
    
    var yValue = function(d) {
      return d.time;
    }; // data -> value
    var yMap = function(d) {
      return yScale(yValue(d));
    };
    var yAxis = d3.svg.axis()
      .orient("left")
      .scale(yScale).ticks(24).tickFormat(d3.time.format("%H:%M"));
    
    // define the x axis
    // setup x 
    var xValue = function(d) {
      return d.date;
    }; // data -> value
    // value -> display
    xMap = function(d) {
      return xScale(xValue(d));
    };
    var xAxis = d3.svg.axis()
      .orient("bottom")
      .scale(xScale).tickFormat(d3.time.format("%Y-%m-%d"));
    
    // draw y axis with labels and move in from the size by the amount of padding
    vis.append("g")
      .attr("transform", "translate(" + padding + ",0)")
      .call(yAxis);
    
    // draw x axis with labels and move to the bottom of the chart area
    vis.append("g")
      .attr("class", "xaxis") // give it a class so it can be used to select only xaxis labels  below
      .attr("transform", "translate(0," + (height - padding) + ")")
      .call(xAxis);
    
    // draw dots
    vis.selectAll(".dot")
      .data(data)
      .enter().append("circle")
      .attr("class", "dot")
      .attr("r", 3.5)
      .attr("cx", xMap)
      .attr("cy", yMap)
      .style("fill", function(d) {
        return color(cValue(d));
      })
      .on("mouseover", function(d) {
        tooltip.transition()
          .duration(200)
          .style("opacity", .9);
        tooltip.html(d["Cereal Name"] + "<br/> (" + xValue(d) +
            ", " + yValue(d) + ")")
          .style("left", (d3.event.pageX + 5) + "px")
          .style("top", (d3.event.pageY - 28) + "px");
      })
      .on("mouseout", function(d) {
        tooltip.transition()
          .duration(500)
          .style("opacity", 0);
      });
    
    // now rotate text on x axis
    // solution based on idea here: https://groups.google.com/forum/?fromgroups#!topic/d3-js/heOBPQF3sAY
    // first move the text left so no longer centered on the tick
    // then rotate up to get 45 degrees.
    vis.selectAll(".xaxis text") // select all the text elements for the xaxis
      .attr("transform", function(d) {
        return "translate(" + this.getBBox().height + "," + this.getBBox().height +")";
      });
    // draw legend
    var legend = vis.selectAll(".legend")
      .data(color.domain())
      .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) {
        return "translate(0," + i * 20 + ")";
      });
    
    // draw legend colored rectangles
    legend.append("rect")
      .attr("x", width - 18)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", color);
    
    // draw legend text
    legend.append("text")
      .attr("x", width - 24)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "end")
      .text(function(d) {
        return d;
      });
    body {
      font: 11px sans-serif;
    }
    
    .axis path,
    .axis line {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }
    
    .dot {
      stroke: #000;
    }
    
    .tooltip {
      position: absolute;
      width: 200px;
      height: 28px;
      pointer-events: none;
    }
    <html>
    
    <head>
      <title>D3 Axis Example</title>
      <script src="http://d3js.org/d3.v2.js"></script>
    </head>
    <style>
    
    </style>
    
    <body>
    
      <script>
      </script>
    
    </body>
    
    </html>

    【讨论】: