kadale
March 18, 2022, 8:21pm
1
I have plot with a x-axis with type: utc/time
. I would like to draw vertical rects for each day on the a-axis similar to this reference pic. It is easy with Plot.cell, but since the axis is not ordinal, I cannot use cell.
If it was a ordinal axis, I could use Plot.cell with this code.
range = d3.extent([new Date("2022-01-01"), new Date("2022-04-01")]);
extnt = d3.utcDays(...dextent);
Plot.cell(extnt,
{
x: (d) => d,
// y: "name",
fill: "#f0dddd50",
stroke: "white"
})
Similar for saturday and sunday
sunday = d3.utcSunday.range(new Date("2022-01-01"), new Date("2022-04-01"));
satday = d3.utcSaturday.range(new Date("2022-01-01"), new Date("2022-04-01"));
//Saturday
Plot.cell(satday,
{
x: (d) => d,
fill: "#f0dddd80",
stroke: "white"
}),
//Sunday
Plot.cell(sunday,
{
x: (d) => d,
fill: "#f0dddd80",
stroke: "white"
})
Thanks in advance
If y is ordinal and x is temporal (time) then I expect you want Plot.barX (horizontal bars). You can also use the interval option as d3.utcDay if each bar is one day long.
1 Like
kadale
March 18, 2022, 11:54pm
4
@tophtucker thanks for the solution. I forgot to include the sample code in my original post - Vacation Gantt / hashg / Observable . I applied your solution. Couple of issues -
Top most bar is above the rectangles.
The ticks needs to be in middle of rectangles as illustrated in the mockup.
kadale
March 18, 2022, 11:59pm
5
True, as suggested by you , I am using Plot.barX to indicate each entry. To enhance the ux, my team wants vertical bars representing each days as depicted in the mockup.
here is my plot with @tophtucker integrated. - Vacation Gantt / hashg / Observable
1 Like
Here’s my suggestion using barX:
Plot.plot({
x: { axis: "top", round: true },
y: { padding: 0, grid: true },
marks: [
Plot.barX(
d3.utcDay.range(start, end).filter((d) => d.getUTCDay() < 2),
{ interval: d3.utcDay, fillOpacity: 0.15 }
),
Plot.barX(
d3.utcDay.range(start, end).filter((d) => d.getUTCDay() >= 2),
{ interval: d3.utcDay, fillOpacity: 0.05 }
),
Plot.barX(data, {
x1: "startDate",
x2: "endDate",
y: "name",
fill: "name",
inset: 0.5
})
]
})
If you omit the y channel then the barX will span the vertical extent of the chart.
I’m not marking the weekends correctly though… you’ll probably want to fix that.
Re: kadale in the forum: I have plot with a x-axis with type: utc/time. I would like to draw vertical rects for each day on the x-axis similar to this reference pic. It is easy with Plot.cell, but since the axis is not ordinal, I cannot use cell.
3 Likes
Fil
March 19, 2022, 2:42pm
7
Could do all the days as one mark with a variable fillOpacity:
Plot.plot({
x: { axis: "top", round: true },
y: { padding: 0, grid: true },
marks: [
Plot.barX(d3.utcDay.range(start, end), {
interval: d3.utcDay,
fillOpacity: (d) => ((1 + d.getUTCDay()) % 7 < 2 ? 0.15 : 0.05)
}),
Plot.barX(data, {
x1: "startDate",
x2: "endDate",
y: "name",
fill: "name",
inset: 0.5
})
],
opacity: { type: "identity" }
})
1 Like
kadale
March 21, 2022, 4:56am
8
Thanks @mbostock and @Fil for investing time to answer my question, the recommendations are working.
Would it be possible to center the ticks on corresponding bar/rect instead of beginning?
Fil
March 21, 2022, 6:26am
9
You could try with the following definition for the ticks on the x axis:
x: {
axis: "top",
round: true,
ticks: {
range(a, b) {
return d3.utcWeek.range(a, b).map((d) => d3.utcHour.offset(d, 12));
}
},
tickFormat: "%b %-d"
},
The ticks will be the same as those generated by d3.utcWeek.range, but shifted by 12 hours. The tickFormat will show the date instead of the default 12AM. (A bit complicated, but dealing with time is always complicated.)
1 Like
kadale
March 21, 2022, 2:57pm
10
Awesome it works. Thanks again.
For what it’s worth, we’re also considering some tweaks to how temporal axes are rendered that would hopefully improve the default appearance.
opened 06:43PM - 23 Jul 21 UTC
closed 06:19PM - 01 Feb 23 UTC
enhancement
It would be useful to be able to make axes like this:
<br /><br />
![image… ](https://user-images.githubusercontent.com/114388/126826951-c60e6b6c-6836-4b40-9868-3d29966bcf4c.png)
One way would be to support multi-line text labels.
Another option would be to allow SVG nodes to be used as ticks rather than coercing the output of `tickFormat` to a string, which is the current behavior.
Here is a notebook which "almost works": https://observablehq.com/d/7de079c962f419f8
kadale
March 21, 2022, 10:35pm
12
I’m waiting for it. I need to display year and month in different ticks.