d3.js 漂亮的结束刻度超出域



我遇到了一个问题,我需要在我的一个轴刻度上使用.nice(),以便刻度线利用端点并正确展开(而不是不使用端点)。

现在我解决了这个问题,出现了一个意想不到的问题。在我这样打电话.nice()之后:

var x = d3.time.scale().range([0, width])
x.domain(d3.extent(data, function(d) { return d.date; })).nice();

轴现在的范围到2018年。这可能会带来麻烦,因为它看起来非常自命不凡,因为它只是2017年2月。显然我没有水晶球,我的数据中任何地方都没有 2018,所以我唯一的猜测是该函数在插值时过火了。

我喜欢/从字面上需要从.nice()或等效的东西插值的刻度间距,但同时我不能在我的数据领域之外进行插值。还有其他人遇到过这个问题吗?可以带来什么?

你处于岩石和坚硬的地方之间。

这里的问题是 D3 轴生成器(特别是在使用时间刻度时)的创建没有考虑到此类自定义。

让我们看看你的问题:使用nice()时,你会得到结束刻度。但是,正如您所说,最终值可能会超过域,这是一个众所周知的问题。

这是一个演示,结束日期是今天,但轴转到 2020 年:

var svg = d3.select("svg");
var xScale = d3.scaleTime().domain([new Date("1980-01-01"), new Date()]).range([20,480]).nice();
var xAxis = d3.axisBottom(xScale);
var gX = svg.append("g").attr("transform","translate(0,50)").call(xAxis);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="80"></svg>

一种可能的解决方案是将concat与秤的域一起使用,以保证域中的第一个和最后一个值将是第一个和最后一个即时报价,如下所示:

.tickValues(xScale.ticks(10).concat(xScale.domain()))

并使用ticks设置大致的刻度数。这是演示:

var svg = d3.select("svg");
var xScale = d3.scaleTime().domain([new Date("1980-01-01"), new Date()]).range([20,480]);
var xAxis = d3.axisBottom(xScale).tickFormat(d3.timeFormat("%Y")).tickValues(xScale.ticks(10).concat(xScale.domain()));
var gX = svg.append("g").attr("transform","translate(0,50)").call(xAxis);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="80"></svg>

但是,如您所见,刻度并不如您所愿地分布均匀。

因此,您的问题的另一种解决方案(仍然使用这种concat方法)是调整ticks值,直到我们使刻度看起来或多或少均匀分布:

var svg = d3.select("svg");
var xScale = d3.scaleTime().domain([new Date("1980-01-01"), new Date()]).range([20,480]);
var xAxis = d3.axisBottom(xScale).tickFormat(d3.timeFormat("%Y")).tickValues(xScale.ticks(5).concat(xScale.domain()));
var gX = svg.append("g").attr("transform","translate(0,50)").call(xAxis);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="80"></svg>

话虽如此,这不是一个正确的解决方案,因为我怀疑任何人都可以(在没有繁琐的黑客的情况下)在确切的域限制处开始和结束轴,并使所有刻度均匀分布。

这应该通过D3.js v6来解决。将d3.scaleTime().nice()一起使用时,可以轻松解决域外的结束勾号问题。但是,请注意d3.scaleUtc().将d3.scaleUtc().nice()一起使用时,相同的问题仍然存在 - 因此只需切换到d3.scaleTime().:)

最新更新