【问题标题】:Fixing the axis-scale range that is presented修复显示的轴比例范围
【发布时间】:2020-10-06 12:18:15
【问题描述】:

我的值是我在时间序列中呈现的总分钟数。虽然分钟用于绘图,但我想更改轴刻度标签以显示此数据最接近的小时数。我解决这个问题的方法是添加一个.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>

【问题讨论】:

    标签: d3.js


    【解决方案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>

    【讨论】:

    • 这很有意义。比我预期的要容易得多。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2012-12-18
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    • 2015-06-10
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多