D3JS makes date duplicates

后端 未结 1 343
长发绾君心
长发绾君心 2021-01-15 17:03

I have this d3js code:

var tooltip = tooltipd3();
        var svg = d3.select(\"svg#svg-day\"),
            margin = {
                top: 20,
                      


        
相关标签:
1条回答
  • 2021-01-15 17:29

    This is something that bothers a lot of people new to D3: the ticks in the axis, specially when using a time scale, are automatically generated. In your case, given the date interval in your domain, it coincidentally ended up creating two ticks for each day. But pay attention to this: those ticks represent different times (hours) in the same day (you can see that if you remove the tickFormat in the axis generator).

    Let's see your code generating the x axis:

    var svg = d3.select("svg");
    var data = d3.csvParse(d3.select("#csv").text());
    var parseTime = d3.timeParse("%Y-%m-%d");
    data.forEach(function(d) {
      d.periodo = parseTime(d.periodo)
    });
    var x = d3.scaleTime()
      .range([20, 480])
      .domain(d3.extent(data, function(d) {
        return d.periodo;
      }));
    
    var axis = d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m"))(svg.append("g").attr("transform", "translate(0,50)"));
    pre {
      display: none;
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg width="500"></svg>
    <pre id="csv">periodo,guadagno
    2017-05-08,0.0
    2017-05-09,0.5385
    2017-05-10,0.0
    2017-05-11,0.0
    2017-05-12,0.0
    2017-05-13,0.5680
    2017-05-14,0.0
    2017-05-15,0.0</pre>

    As you can see, there are two ticks for each day (remember, for different hours).

    Let's show that this is a coincidence: This is the same code, but changing the last date for 2017-05-20:

    var svg = d3.select("svg");
    var data = d3.csvParse(d3.select("#csv").text());
    var parseTime = d3.timeParse("%Y-%m-%d");
    data.forEach(function(d) {
      d.periodo = parseTime(d.periodo)
    });
    var x = d3.scaleTime()
      .range([20, 480])
      .domain(d3.extent(data, function(d) {
        return d.periodo;
      }));
    
    var axis = d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m"))(svg.append("g").attr("transform", "translate(0,50)"));
    pre {
      display: none;
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg width="500"></svg>
    <pre id="csv">periodo,guadagno
    2017-05-08,0.0
    2017-05-09,0.5385
    2017-05-10,0.0
    2017-05-11,0.0
    2017-05-12,0.0
    2017-05-13,0.5680
    2017-05-14,0.0
    2017-05-20,0.0</pre>

    Back to your code.

    The solution is quite simple: using intervals. Let's set the interval for each tick:

    d3.axisBottom(x).ticks(d3.timeDay)
    

    Here is the same code with that change only:

    var svg = d3.select("svg");
    var data = d3.csvParse(d3.select("#csv").text());
    var parseTime = d3.timeParse("%Y-%m-%d");
    data.forEach(function(d) {
      d.periodo = parseTime(d.periodo)
    });
    var x = d3.scaleTime()
      .range([20, 480])
      .domain(d3.extent(data, function(d) {
        return d.periodo;
      }));
    
    var axis = d3.axisBottom(x).tickFormat(d3.timeFormat("%d/%m")).ticks(d3.timeDay)(svg.append("g").attr("transform", "translate(0,50)"));
    pre {
      display: none;
    }
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg width="500"></svg>
    <pre id="csv">periodo,guadagno
    2017-05-08,0.0
    2017-05-09,0.5385
    2017-05-10,0.0
    2017-05-11,0.0
    2017-05-12,0.0
    2017-05-13,0.5680
    2017-05-14,0.0
    2017-05-15,0.0</pre>

    0 讨论(0)
提交回复
热议问题