我在d3中有一个折线图。 x轴是日期。我想稍微扩大范围,以使第一个和最后一个数据点不会恰好位于图表的第一个和最后一个日期。这是图表的图片:
javascript - 如何在d3中的日期轴上增加范围?-LMLPHP

注意第一个数据点和最后一个数据点在图表的开始和结尾处如何正确?我要在双方上留一点余地,这是最小日期应小一些,最大日期应大一些。有没有简单的方法来扩展范围?

当前创建方式如下:

x.domain(d3.extent(data, function(d) { return d.date; }));


编辑:日期是动态的,可能是几天或几十年。我希望找到一个可以查看日期范围的答案,并在每个结尾处增加5%之类的答案。另外,请提供不依赖于添加其他库的解决方案,这可能会与现有库功能冲突。

例如,Gerardo下面的解决方案取决于添加一个额外的库以使count函数起作用。但这会干扰代码后面的轴功能。

使以下代码起作用的唯一方法:

  const minDate = new Date("October 10, 2010");
  const maxDate = new Date("January 31, 2020");
  const daysBetween = d3.timeDay.count(minDate,maxDate);


包括此库:

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>


但这导致下面的代码在以后使用时失败:

  var xAxis = d3.svg.axis()
    .scale(x)
    .ticks(d3.time.years,1)
    .tickSize(10)
    .orient("bottom");


这是我的解决方案。我从范围中获取最小和最大日期,将其转换为毫秒,然后从最小值中减去5%,将5%添加到最大值,然后设置新的范围:

  var xSpan = maxTime - minTime;
  console.log("maxTime=" +maxTime +", minTime=" +minTime +", xSpan="+xSpan);
  xMarg = xSpan * 0.05;
  xMarg = xMarg.toFixed(0); //nearest millisecond
  console.log("xMarg="+xMarg);
  var minDate = new Date(minTime-xMarg);
  var maxDate = new Date(maxTime+xMarg);
  console.log("minDate="+minDate +", maxDate="+maxDate);
  x.domain([minDate,maxDate]);


但是maxDate输出显示错误:


  maxTime = 1580454000000,minTime = 1288332000000,xSpan = 292122000000
  xMarg = 14606100000 minDate =星期三2010年5月12日22:45:00 GMT-0600
  (夏令时),maxDate =无效日期

最佳答案

d3-time模块有一些方便的方法,您可以使用interval.offset。您可以选择是否要添加/减去毫秒,秒,分钟,小时,天,周,月或年。

例如,如果您想为日期添加15天,例如今天:



const todayPlus15days = d3.timeDay.offset(new Date(), 15);
//Interval type and offset-----^-----------------------^

console.log("In 15 days, it will be: " + todayPlus15days);

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>





对于您的情况,让我们减去/增加2个月。为此,我们将d3.extent更改为d3.min / d3.max

x.domain([d3.timeMonth.offset(d3.min(data, function(d) {
    return d.date;
  }), -2),//subtracting 2 months
  d3.timeMonth.offset(d3.max(data, function(d) {
    return d.date;
  }), 2)//adding 2 months
])


值得一提的是,d3.timeMonth.offset(date, 2)似乎与d3.timeDay.offset(date, 60)相同,但是60天不一定是2个月。但是,对于您而言,这种精度并不重要。



编辑

根据your comment


  到目前为止,所有答案都假定一个已知的日期范围。日期范围可能是几天或几十年。我希望找到一个可以查看日期范围的答案,并在每个结尾处增加5%之类的答案。


这也很容易实现。首先,我们设置百分比(例如5%),然后获得日期间隔。为了获得更高的精度,您可以使用秒甚至毫秒,但是这里我将使用天(d3.timeDay.count)。最后,根据百分比设置偏移量(开始/结束)。

这是一个演示:



const date1 = new Date("March 19, 2019");
const date2 = new Date("December 10, 2019");
const percentage = 0.05;
const numberOfDays = d3.timeDay.count(date1, date2);
const domain = [d3.timeDay.offset(date1, -(~~(numberOfDays * percentage))),
  d3.timeDay.offset(date2, +(~~(numberOfDays * percentage)))
];

console.log(domain)

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

10-06 04:39
查看更多