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.