D3 JS - tick spacing on time axis gets messed up by month boundary

一笑奈何 提交于 2020-01-13 16:54:08

问题


Using d3.js, I found that when using a time scale for the x-axis, the major tick marks get messed up on a new month boundary. It appears to create a new tick mark on the new month even if that results in a tick too close to the previous tick. Not only does this mess up the even spacing along the axis, it also makes the tick labels overlap and look pretty ugly.

See the demo at the bottom of the question to show what I mean (scroll to the right to see the problem area).

Do I need a custom multi-scale time format to handle this case? Or is there some option I'm missing here? (And is this considered a bug?)

EDIT: I tried out the custom multi-time format, and it does work to change the extra label from just "June" to match the others, but it still shows up where it shouldn't. The problem is that there shouldn't be a tick mark there at all; it should keep the same 2-day spacing between ticks that was always there, and it's not. I'm leaning toward calling this a bug.

Here's a demo where this happens:

<!DOCTYPE html>
    <meta charset="utf-8">
    <style>
      body {
        font: 12px Arial;
      }
      path {
        stroke: steelblue;
        stroke-width: 2;
        fill: none;
      }
      .axis path, .axis line {
        fill: none;
        stroke: grey;
        stroke-width: 1;
        shape-rendering: crispEdges;
      }
    </style>
    <body>
      <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.2.2/d3.v3.min.js"></script>
      <script type="text/javascript">
        var data = {
            "values" : [40, 80, 94, 95, 10, 81, 89, 70, 43, 56, 86, 72, 39, 38, 84, 5, 0, 38, 68, 16, 23, 6, 45, 7, 79, 59, 51, 33, 44, 18],
            "labels" : ["2013,05,07", "2013,05,08", "2013,05,09", "2013,05,10", "2013,05,11", "2013,05,12", "2013,05,13", "2013,05,14", "2013,05,15", "2013,05,16", "2013,05,17", "2013,05,18", "2013,05,19", "2013,05,20", "2013,05,21", "2013,05,22", "2013,05,23", "2013,05,24", "2013,05,25", "2013,05,26", "2013,05,27", "2013,05,28", "2013,05,29", "2013,05,30", "2013,05,31", "2013,06,01", "2013,06,02", "2013,06,03", "2013,06,04", "2013,06,05"]
        };
    
        var margin = { top : 15, right : 15, bottom : 40, left : 50 },
            width = 750 - margin.left - margin.right,
            height = 250 - margin.top - margin.bottom;
    
        // Parse dates
        data.parsedDates = [];
        data.labels.forEach(function(d) {
            var parsed = d3.time.format("%Y,%m,%d").parse(d);
            data.parsedDates.push(parsed);
        });
    
        var x = d3.time.scale()
            .range([0, width])
            .domain(d3.extent(data.parsedDates));
    
        var y = d3.scale.linear()
            .range([height, 0])
            .domain(d3.extent(data.values));
    
        var xAxis = d3.svg.axis().scale(x)
            .ticks(8).tickSize(5, 0, 0);
    
        var line = d3.svg.line()
            .x(function(d,i) {
                return x(data.parsedDates[i]); })
            .y(function(d,i) {
                return y(d); });
    
        // Create chart
        var svg = 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 + ")");
    
        // Graph points
        svg.append("path")
          .datum(data)
          .attr("class", "line")
          .attr("d", function(d) { return line(d.values) });
    
        // Add the X Axis
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);
      </script>
    </body>

回答1:


Seems that manual dates selection is the only possible solution for current D3 version, 5.12.0 as for answer date (P.S. solution mentioned here):

const xValues = data.filter((d, i) => i % interval === 0).map(d => d.date);

const xAxis = d3.axisBottom(x)
.tickFormat(d3.timeFormat('%b %d'))
// .ticks(d3.timeDay.every(interval))
.tickValues(xValues);


来源:https://stackoverflow.com/questions/17369542/d3-js-tick-spacing-on-time-axis-gets-messed-up-by-month-boundary

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!