Used inside Plot
Plot.ruleX(today, { stroke: "red" })
Today defined with new Date() - DOES NOT WORK
today = [new Date()];
Today defined with new Date(2022,2,21) - WORKS
today = [new Date(2022,2,21)];
Reference code:
Used inside Plot
Plot.ruleX(today, { stroke: "red" })
Today defined with new Date() - DOES NOT WORK
today = [new Date()];
Today defined with new Date(2022,2,21) - WORKS
today = [new Date(2022,2,21)];
Reference code:
The issue is that you’re implicitly defining an ordinal (point) scale because you’ve specified a domain with more than two values. Since the domain doesn’t include the rule’s date (today), the plot is invalid. I suspect that you want to define the domain as domain: [start, end] instead so that you get a continuous (utc) scale.
Thanks a lot for the analysis. It means a lot coming from you.
When I switch the domain to domain: [start, end], the scale shows only months Jan, Feb, Mar.
What would be the right way to display every day always on x-axis?
@mbostock I tried this
let start = new Date(2022, 0, 1);
let end = new Date(2022, 2, 1);
let rangeCount = d3.timeDay.count(start, end);
Plot.plot({
.....
grid: true,
x: {
axis: "top",
domain: [start, end],
range: [0, rangeCount],
tickFormat: (d) => formatDay(d)
},
It does not render every date on x-axis, only displays `Jan, Mar`
Thanks in advance.
Using the ticks option. Something like
x: {
axis: "top",
domain: [start, end],
ticks: d3.utcDay,
tickSize: 0,
tickFormat: formatDay
},
It worked! But When I add data
Plot.cell(data, {
y: "name",
x: (d) => d.date,
fill: (d) => d.country,
title: (d) => `${d.name}\n${d.country}`
})
x-axis resets back to Jan, Mar.
Updated - https://observablehq.com/@hashg/plot-now
I’m in process of building a gantt-calendar similar to this,
Plot, is it a good choice?It resets because Plot.cell implies that both x and y are ordinal scales, so you’re back to where you started.
(If you specify x: {type: "utc"} you’ll see an error when you try to use Plot.cell.)
You want a Plot.barX, not a Plot.cell here, because x is continuous (representing a time interval with a start and stop) and y is ordinal. And you’ll typically want to specify the start and stop time of each period of work, something like
Plot.barX(data, {
y: "name",
x1: (d) => d.startDate,
x2: (d) => d.endDate,
fill: (d) => d.country,
title: (d) => `${d.name}\n${d.country}`
})
If you don’t have a start and stop date, and instead you have periodic sampling (like, every day), you could use the interval option instead:
Plot.barX(data, {
y: "name",
x: (d) => d.date,
interval: d3.utcDay,
fill: (d) => d.country,
title: (d) => `${d.name}\n${d.country}`
})
I’ll also note that your notebook is currently using local time. That’s fine if all of your viewers are in the same time zone, but if your viewers might be in different time zones, then you’ll want to use UTC instead. And also note that Plot defaults to UTC with temporal data, so you’ll need to say x: {type: "time"} (rather than x: {type: "utc"}, or not specifying the scale type).
(You’ll also want to avoid the mutation you’re currently doing by calling setHours as this leads to unpredictable behavior with Observable dataflow.)
I’d probably do something like this:
Plot.plot({
width,
height: 200,
label: null,
x: {
axis: "top",
domain: [start, end]
},
y: {
grid: true
},
marks: [
Plot.ruleX(d3.utcDay.range(start, end), { strokeOpacity: 0.1 }),
Plot.ruleX([today], { stroke: "red" }),
Plot.barX(data, {
y: "NAME",
x: "DATE",
interval: d3.utcDay,
inset: 0, // no gaps between days
fill: "COUNTRY",
title: (d) => `${d.NAME}\n${d.COUNTRY}`
})
]
})
Live notebook: Plot now / Mike Bostock / Observable
Thanks again.
I learnt lot more about ordinal scales, utc, choosing right plot type. Highly valued feedback. ![]()