Reputation: 7162
I want to create a tick on my chart every Nth day, with the number of days configurable. If the user chooses "30 days", then the scale should show a tick every 30 days.
To do so, what I've tried is to pass an interval with d3.timeDay
. The issue is that D3 docs tell me the dates are not uniformly spaced. Furthermore, it doens't work above 30 days.
d3.timeDay.every(30).range(new Date(2015, 0, 1), new Date(2015, 2, 1));
// returns
[
2015-01-01,
2015-01-31,
2015-02-01,
]
How can I get uniformly spaced dates (and ticks?)
const dom = [new Date(2019, 1, 1), new Date(2020, 1, 1)]
const width = 600
const height = 200
const x = d3.scaleTime()
.domain(dom)
.range([0, width])
d3.select("body")
.append("svg")
.attr("viewBox", [0, 0, width, height])
.append("g")
.call(d3.axisBottom(x)
.ticks(d3.timeDay.every(30))
.tickFormat(d3.timeFormat("%d-%m-%Y")))
<script src="https://d3js.org/d3.v6.min.js"></script>
Upvotes: 0
Views: 1088
Reputation: 7162
I managed to do it with d3.count()
, filtering every date that comes and checking the spacing against the first date. Feel free to answer if there's a better solution.
const dom = [new Date(2019, 1, 1), new Date(2020, 1, 1)]
const width = 600
const height = 200
const x = d3.scaleTime()
.domain(dom)
.range([0, width])
d3.select("body")
.append("svg")
.attr("viewBox", [0, 0, width, height])
.append("g")
.call(d3.axisBottom(x)
.ticks(d3.timeDay.filter(d => d3.timeDay.count(dom[0], d) % 30 === 0))
.tickFormat(d3.timeFormat("%d-%m-%Y")))
<script src="https://d3js.org/d3.v6.min.js"></script>
Upvotes: 4