固定显示的轴刻度范围

时间:2020-10-06 12:18:15

标签: d3.js

我有一个值,它是我在时间序列中显示的总分钟数。在使用分钟进行绘图的同时,我想更改轴刻度标签以显示该数据最接近的小时数。我解决此问题的方法是添加一个.tickFormat(),将分钟转换为小时,然后返回带有小时格式的d3.timeFormat()和一个新的设置为0的日期,该日期设置为小时。轴刻度标签关闭时,它们是不正确的。似乎有一点偏移,值重复并且刻度不从0开始(从12开始)。我应该使用其他函数调用来更正比例尺吗?。

这是有问题的代码

svg.append("g")
        .call(d3.axisLeft()
            .scale(y)
            .tickFormat((d, i) => {
                var hours = Math.floor(d / 60);
                console.log(hours)
                console.log(new Date(0).setMinutes(hours))
                return d3.timeFormat("%I")( new Date(0).setHours(hours))
            }));

<meta charset="utf-8">

<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

<style>
div.tooltip {   
    position: absolute;         
    text-align: center;         
    width: 100px;                   
    height: 30px;                   
    padding: 2px;               
    font: 12px sans-serif;      
    background: lightsteelblue; 
    border: 0px;        
    border-radius: 8px;         
    pointer-events: none;           
}
</style>

<script>

    var data = [
        { "x": "2020-04-26", "y": 461.0, "label": "7:41" },
        { "x": "2020-04-27", "y": 421.0, "label": "7:01" },
        { "x": "2020-04-28", "y": 519.0, "label": "8:39" },
        { "x": "2020-04-29", "y": 502.0, "label": "8:22" },
        { "x": "2020-04-30", "y": 511.0, "label": "8:31" },
        { "x": "2020-05-01", "y": 513.0, "label": "8:33" },
        { "x": "2020-05-02", "y": 496.0, "label": "8:16" },
        { "x": "2020-05-03", "y": 480.0, "label": "8:00" },
        { "x": "2020-05-04", "y": 364.0, "label": "6:04" },
        { "x": "2020-05-05", "y": 498.0, "label": "8:18" },
        { "x": "2020-05-06", "y": 467.0, "label": "7:47" },
        { "x": "2020-05-07", "y": 477.0, "label": "7:57" },
        { "x": "2020-05-08", "y": 431.0, "label": "7:11" },
        { "x": "2020-05-09", "y": 419.0, "label": "6:59" },
        { "x": "2020-05-10", "y": 471.0, "label": "7:51" },
        { "x": "2020-05-11", "y": 391.0, "label": "6:31" },
        { "x": "2020-05-12", "y": 481.0, "label": "8:01" },
        { "x": "2020-05-13", "y": 494.0, "label": "8:14" },
        { "x": "2020-05-14", "y": 506.0, "label": "8:26" },
        { "x": "2020-05-15", "y": 464.0, "label": "7:44" },
        { "x": "2020-05-16", "y": 474.0, "label": "7:54" },
        { "x": "2020-05-17", "y": 383.0, "label": "6:23" },
        { "x": "2020-05-18", "y": 385.0, "label": "6:25" },
        { "x": "2020-05-19", "y": 470.0, "label": "7:50" },
        { "x": "2020-05-20", "y": 465.0, "label": "7:45" },
        { "x": "2020-05-21", "y": 574.0, "label": "9:34" },
        { "x": "2020-05-22", "y": 473.0, "label": "7:53" },
        { "x": "2020-05-23", "y": 431.0, "label": "7:11" },
        { "x": "2020-05-24", "y": 497.0, "label": "8:17" },
        { "x": "2020-05-26", "y": 482.0, "label": "8:02" },
        { "x": "2020-05-27", "y": 492.0, "label": "8:12" },
        { "x": "2020-05-28", "y": 494.0, "label": "8:14" },
        { "x": "2020-05-29", "y": 469.0, "label": "7:49" },
        { "x": "2020-05-30", "y": 395.0, "label": "6:35" },
        { "x": "2020-05-31", "y": 427.0, "label": "7:07" },
        { "x": "2020-06-01", "y": 346.0, "label": "5:46" },
        { "x": "2020-06-02", "y": 416.0, "label": "6:56" },
        { "x": "2020-06-03", "y": 461.0, "label": "7:41" },
        { "x": "2020-06-04", "y": 486.0, "label": "8:06" },
        { "x": "2020-06-05", "y": 451.0, "label": "7:31" },
        { "x": "2020-06-06", "y": 533.0, "label": "8:53" },
        { "x": "2020-06-08", "y": 462.0, "label": "7:42" },
        { "x": "2020-06-09", "y": 461.0, "label": "7:41" },
        { "x": "2020-06-10", "y": 477.0, "label": "7:57" },
        { "x": "2020-06-11", "y": 458.0, "label": "7:38" },
        { "x": "2020-06-12", "y": 484.0, "label": "8:04" },
        { "x": "2020-06-13", "y": 389.0, "label": "6:29" },
        { "x": "2020-06-15", "y": 472.0, "label": "7:52" },
        { "x": "2020-06-16", "y": 462.0, "label": "7:42" },
        { "x": "2020-06-17", "y": 486.0, "label": "8:06" },
        { "x": "2020-06-18", "y": 489.0, "label": "8:09" },
        { "x": "2020-06-19", "y": 483.0, "label": "8:03" },
        { "x": "2020-06-20", "y": 426.0, "label": "7:06" },
        { "x": "2020-06-21", "y": 453.0, "label": "7:33" },
        { "x": "2020-06-22", "y": 489.0, "label": "8:09" },
        { "x": "2020-06-23", "y": 467.0, "label": "7:47" },
        { "x": "2020-06-24", "y": 474.0, "label": "7:54" },
        { "x": "2020-06-25", "y": 451.0, "label": "7:31" },
        { "x": "2020-06-26", "y": 450.0, "label": "7:30" },
        { "x": "2020-06-27", "y": 470.0, "label": "7:50" },
        { "x": "2020-06-29", "y": 247.0, "label": "4:07" },
        { "x": "2020-06-30", "y": 502.0, "label": "8:22" },
        { "x": "2020-07-01", "y": 464.0, "label": "7:44" }
    ]
    
    // D3 date parser
    for (var i=0; i < data.length; i++){
        var parser = d3.timeParse("%Y-%m-%d")
        data[i].date = parser(data[i].x);
    }

    var margin = { top: 10, right: 30, bottom: 30, left: 60  }
    var width = 800 - margin.left - margin.right;
    var height = 800 - margin.top - margin.bottom;


    // Define the div for the tooltip
    var div = d3.select("body").append("div")   
        .attr("class", "tooltip")               
        .style("opacity", 0);

    var svg = d3.select("#my_dataviz")
        .append("svg")
            .attr( 'preserveAspectRatio',"xMinYMin meet")
            .attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom))
        .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)

    var x = d3.scaleTime()
        .domain([d3.min(data, function(d) { return d.date }), d3.max(data, function(d) { return d.date })])
        .range([0, width]);
    
    svg.append("g")
        .attr("transform", "translate(" + 0 + "," + height + ")")
        .call(d3.axisBottom(x));

    // text label for the x axis
    svg.append("text")             
        .attr("transform",
                "translate(" + (width/2) + " ," + (height + margin.top + 20) + ")")
        .style("text-anchor", "middle")
        .text("Date");

    var y = d3.scaleLinear()
        .domain([0, d3.max(data, function(d){ return +d.y })])
        .range([height, 0]);
    
    svg.append("g")
        .call(d3.axisLeft()
            .scale(y)
            .tickFormat((d, i) => {
                var hours = Math.floor(d / 60);
                console.log(hours)
                console.log(new Date(0).setMinutes(hours))
                return d3.timeFormat("%I")( new Date(0).setHours(hours))
            }));

    // text label for the y axis
    svg.append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 0 - margin.left)
        .attr("x",0 - (height / 2))
        .attr("dy", "1em")
        .style("text-anchor", "middle")
        .text("Time Asleep (Minutes)");

    // Add line path
    svg.append("path")
        .datum(data)
        .attr("fill", "none")
        .attr("stroke", "steelblue")
        .attr("stroke-width", 1.5)
        .attr("d", d3.line()
            .x(function(d) { return x(d.date) })
            .y(function(d) { return y(d.y) })
        );

    // Add the scatterplot (data points)
    svg.selectAll("dot")
        .data(data)
    .enter().append("circle")
        .attr("r", 3)
        // Add tooltip on hover
        .on("mouseover", function(d) {
            div.transition()
                .duration(200)
                .style("opacity", .9);
            div.html(d.x + "<br/>" + d.label)
                .style("left", (d3.event.pageX) + "px")
                .style("top", (d3.event.pageY - 30) + "px")
        })
        // Remove tooltip after hover
        .on("mouseout", function(d) {
            div.transition()
                .duration(500)
                .style("opacity", 0);
        })
        .transition()
        .delay(function(d,i){ return (i*3)})
        .duration(2000)
        .attr("cx", function(d){ return x(d.date) })
        .attr("cy", function(d){ return y(d.y) });
    

</script>

1 个答案:

答案 0 :(得分:1)

虽然数据是时间,但不是日期。强迫它约会会给您带来很多麻烦。我刚刚超越了d3和Date逻辑,从而得出了一个更简单的解决方案:

var data = [{
    "x": "2020-04-26",
    "y": 461.0,
    "label": "7:41"
  },
  {
    "x": "2020-04-27",
    "y": 421.0,
    "label": "7:01"
  },
  {
    "x": "2020-04-28",
    "y": 519.0,
    "label": "8:39"
  },
  {
    "x": "2020-04-29",
    "y": 502.0,
    "label": "8:22"
  },
  {
    "x": "2020-04-30",
    "y": 511.0,
    "label": "8:31"
  },
  {
    "x": "2020-05-01",
    "y": 513.0,
    "label": "8:33"
  },
  {
    "x": "2020-05-02",
    "y": 496.0,
    "label": "8:16"
  },
  {
    "x": "2020-05-03",
    "y": 480.0,
    "label": "8:00"
  },
  {
    "x": "2020-05-04",
    "y": 364.0,
    "label": "6:04"
  },
  {
    "x": "2020-05-05",
    "y": 498.0,
    "label": "8:18"
  },
  {
    "x": "2020-05-06",
    "y": 467.0,
    "label": "7:47"
  },
  {
    "x": "2020-05-07",
    "y": 477.0,
    "label": "7:57"
  },
  {
    "x": "2020-05-08",
    "y": 431.0,
    "label": "7:11"
  },
  {
    "x": "2020-05-09",
    "y": 419.0,
    "label": "6:59"
  },
  {
    "x": "2020-05-10",
    "y": 471.0,
    "label": "7:51"
  },
  {
    "x": "2020-05-11",
    "y": 391.0,
    "label": "6:31"
  },
  {
    "x": "2020-05-12",
    "y": 481.0,
    "label": "8:01"
  },
  {
    "x": "2020-05-13",
    "y": 494.0,
    "label": "8:14"
  },
  {
    "x": "2020-05-14",
    "y": 506.0,
    "label": "8:26"
  },
  {
    "x": "2020-05-15",
    "y": 464.0,
    "label": "7:44"
  },
  {
    "x": "2020-05-16",
    "y": 474.0,
    "label": "7:54"
  },
  {
    "x": "2020-05-17",
    "y": 383.0,
    "label": "6:23"
  },
  {
    "x": "2020-05-18",
    "y": 385.0,
    "label": "6:25"
  },
  {
    "x": "2020-05-19",
    "y": 470.0,
    "label": "7:50"
  },
  {
    "x": "2020-05-20",
    "y": 465.0,
    "label": "7:45"
  },
  {
    "x": "2020-05-21",
    "y": 574.0,
    "label": "9:34"
  },
  {
    "x": "2020-05-22",
    "y": 473.0,
    "label": "7:53"
  },
  {
    "x": "2020-05-23",
    "y": 431.0,
    "label": "7:11"
  },
  {
    "x": "2020-05-24",
    "y": 497.0,
    "label": "8:17"
  },
  {
    "x": "2020-05-26",
    "y": 482.0,
    "label": "8:02"
  },
  {
    "x": "2020-05-27",
    "y": 492.0,
    "label": "8:12"
  },
  {
    "x": "2020-05-28",
    "y": 494.0,
    "label": "8:14"
  },
  {
    "x": "2020-05-29",
    "y": 469.0,
    "label": "7:49"
  },
  {
    "x": "2020-05-30",
    "y": 395.0,
    "label": "6:35"
  },
  {
    "x": "2020-05-31",
    "y": 427.0,
    "label": "7:07"
  },
  {
    "x": "2020-06-01",
    "y": 346.0,
    "label": "5:46"
  },
  {
    "x": "2020-06-02",
    "y": 416.0,
    "label": "6:56"
  },
  {
    "x": "2020-06-03",
    "y": 461.0,
    "label": "7:41"
  },
  {
    "x": "2020-06-04",
    "y": 486.0,
    "label": "8:06"
  },
  {
    "x": "2020-06-05",
    "y": 451.0,
    "label": "7:31"
  },
  {
    "x": "2020-06-06",
    "y": 533.0,
    "label": "8:53"
  },
  {
    "x": "2020-06-08",
    "y": 462.0,
    "label": "7:42"
  },
  {
    "x": "2020-06-09",
    "y": 461.0,
    "label": "7:41"
  },
  {
    "x": "2020-06-10",
    "y": 477.0,
    "label": "7:57"
  },
  {
    "x": "2020-06-11",
    "y": 458.0,
    "label": "7:38"
  },
  {
    "x": "2020-06-12",
    "y": 484.0,
    "label": "8:04"
  },
  {
    "x": "2020-06-13",
    "y": 389.0,
    "label": "6:29"
  },
  {
    "x": "2020-06-15",
    "y": 472.0,
    "label": "7:52"
  },
  {
    "x": "2020-06-16",
    "y": 462.0,
    "label": "7:42"
  },
  {
    "x": "2020-06-17",
    "y": 486.0,
    "label": "8:06"
  },
  {
    "x": "2020-06-18",
    "y": 489.0,
    "label": "8:09"
  },
  {
    "x": "2020-06-19",
    "y": 483.0,
    "label": "8:03"
  },
  {
    "x": "2020-06-20",
    "y": 426.0,
    "label": "7:06"
  },
  {
    "x": "2020-06-21",
    "y": 453.0,
    "label": "7:33"
  },
  {
    "x": "2020-06-22",
    "y": 489.0,
    "label": "8:09"
  },
  {
    "x": "2020-06-23",
    "y": 467.0,
    "label": "7:47"
  },
  {
    "x": "2020-06-24",
    "y": 474.0,
    "label": "7:54"
  },
  {
    "x": "2020-06-25",
    "y": 451.0,
    "label": "7:31"
  },
  {
    "x": "2020-06-26",
    "y": 450.0,
    "label": "7:30"
  },
  {
    "x": "2020-06-27",
    "y": 470.0,
    "label": "7:50"
  },
  {
    "x": "2020-06-29",
    "y": 247.0,
    "label": "4:07"
  },
  {
    "x": "2020-06-30",
    "y": 502.0,
    "label": "8:22"
  },
  {
    "x": "2020-07-01",
    "y": 464.0,
    "label": "7:44"
  }
]

// D3 date parser
for (var i = 0; i < data.length; i++) {
  var parser = d3.timeParse("%Y-%m-%d")
  data[i].date = parser(data[i].x);
}

var margin = {
  top: 10,
  right: 30,
  bottom: 30,
  left: 60
}
var width = 800 - margin.left - margin.right;
var height = 800 - margin.top - margin.bottom;


// Define the div for the tooltip
var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

var svg = d3.select("#my_dataviz")
  .append("svg")
  .attr('preserveAspectRatio', "xMinYMin meet")
  .attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom))
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)

var x = d3.scaleTime()
  .domain([d3.min(data, function(d) {
    return d.date
  }), d3.max(data, function(d) {
    return d.date
  })])
  .range([0, width]);

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

// text label for the x axis
svg.append("text")
  .attr("transform",
    "translate(" + (width / 2) + " ," + (height + margin.top + 20) + ")")
  .style("text-anchor", "middle")
  .text("Date");

var y = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) {
    return +d.y
  })])
  .range([height, 0]);

svg.append("g")
  .call(d3.axisLeft()
    .scale(y)
    .tickFormat((d, i) => {
      var hours = Math.floor(d / 60);
      var minutes = d - hours * 60;
      return hours.toString().padStart(2, 0) + ":" + minutes.toString().padStart(2, 0).padStart(2, 0);
    }));

// text label for the y axis
svg.append("text")
  .attr("transform", "rotate(-90)")
  .attr("y", 0 - margin.left)
  .attr("x", 0 - (height / 2))
  .attr("dy", "1em")
  .style("text-anchor", "middle")
  .text("Time Asleep (Minutes)");

// Add line path
svg.append("path")
  .datum(data)
  .attr("fill", "none")
  .attr("stroke", "steelblue")
  .attr("stroke-width", 1.5)
  .attr("d", d3.line()
    .x(function(d) {
      return x(d.date)
    })
    .y(function(d) {
      return y(d.y)
    })
  );

// Add the scatterplot (data points)
svg.selectAll("dot")
  .data(data)
  .enter().append("circle")
  .attr("r", 3)
  // Add tooltip on hover
  .on("mouseover", function(d) {
    div.transition()
      .duration(200)
      .style("opacity", .9);
    div.html(d.x + "<br/>" + d.label)
      .style("left", (d3.event.pageX) + "px")
      .style("top", (d3.event.pageY - 30) + "px")
  })
  // Remove tooltip after hover
  .on("mouseout", function(d) {
    div.transition()
      .duration(500)
      .style("opacity", 0);
  })
  .transition()
  .delay(function(d, i) {
    return (i * 3)
  })
  .duration(2000)
  .attr("cx", function(d) {
    return x(d.date)
  })
  .attr("cy", function(d) {
    return y(d.y)
  });
div.tooltip {
  position: absolute;
  text-align: center;
  width: 100px;
  height: 30px;
  padding: 2px;
  font: 12px sans-serif;
  background: lightsteelblue;
  border: 0px;
  border-radius: 8px;
  pointer-events: none;
}
<meta charset="utf-8">

<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

相关问题