Using “fill rules” on a Date Axis

This tutorial will show how to highlight weekends on a Date Axis. It will explain how you can use custom function to force your own custom logic in determining what ranges of dates should be highlighted and how.

Base chart

Let's take a simple Date-based chart.

See the Pen amCharts 4: Using fillRule by amCharts team (@amcharts) on CodePen.0

Enabling axis fills

We do have nice clean grid. No fills.

To start off, we need to enable "Axis fills", that are accessible via Axis renderer's axisFills property.

To enable them, we have to enable them as well as set fill settings:

dateAxis.renderer.axisFills.template.disabled = false;
dateAxis.renderer.axisFills.template.fill = am4core.color("#D2D68D");
dateAxis.renderer.axisFills.template.fillOpacity = 0.2;
dateAxis.renderer.axisFills.template.disabled = false;
dateAxis.renderer.axisFills.template.fill = am4core.color("#D2D68D");
dateAxis.renderer.axisFills.template.fillOpacity = 0.2;
{
// ...
"xAxes": [{
// ...
"renderer": {
"axisFills": {
"disabled": false,
"fill": "#D2D68D",
"fillOpacity": 0.2
}
}
}]
}

Let's see how that turned out.

See the Pen amCharts 4: Using fillRule by amCharts team (@amcharts) on CodePen.0

It worked. We now have axis fills, which is placed every second grid cell by default.

That's not what we wanted, though.

Using custom fill rule

As much as we would like it, every second day is not a weekend.

This means we'll need to apply our own custom logic for determining what days to fill, and what days to leave as they are.

For that exact purpose DateAxis (and ValueAxis for that matter) has a method: fillRule().

It's called every time the Axis renderer is determining whether to place an axis fill or not.

Default one simply colors every second call.

We'll need to replace default fillRule with our one custom function.

dateAxis.fillRule = function(dataItem) {
let date = new Date(dataItem.value);
if (date.getDay() == 0 || date.getDay() == 6) {
dataItem.axisFill.visible = true;
}
else {
dataItem.axisFill.visible = false;
}
}
dateAxis.fillRule = function(dataItem) {
var date = new Date(dataItem.value);
if (date.getDay() == 0 || date.getDay() == 6) {
dataItem.axisFill.visible = true;
}
else {
dataItem.axisFill.visible = false;
}
}
{
// ...
"xAxes": [{
// ...
"fillRule": function(dataItem) {
var date = new Date(dataItem.value);
if (date.getDay() == 0 || date.getDay() == 6) {
dataItem.axisFill.visible = true;
}
else {
dataItem.axisFill.visible = false;
}
}
}]
}

As you can see from the above code, a function takes data item, representing particular axis range.

We check its value which in case of DateAxis contains Date object, and if it's Saturday or Sunday, we make data item's axisFill visible, while hiding it otherwise.

Let's see how it turned out.

See the Pen amCharts 4: Using fillRule by amCharts team (@amcharts) on CodePen.0

Perfect!

There's a caveat, though

There's always one.

DateAxis (and any other axis for that matter) has an automatic granularity control. This means, that if there's not enough space available, it will start skipping intervals - in our case days.

So for example, it might start showing a grid line and label every second day.

In that case our "fill rule" starts falling apart. A single space between grid lines may contain both weekend and normal days, so how do we color that space?

There's no good workaround, so we just need to build a fail-safe in place that would disable axis fills altogether, if the chart is in any other than daily mode.

For that purpose we can check axis' gridInterval property, which will hold current granularity of axis labels.

dateAxis.fillRule = function(dataItem) {
let date = new Date(dataItem.value);
if ((date.getDay() == 0 || date.getDay() == 6) && dateAxis.gridInterval.timeUnit == "day" && dateAxis.gridInterval.count == 1) {
dataItem.axisFill.visible = true;
}
else {
dataItem.axisFill.visible = false;
}
}
dateAxis.fillRule = function(dataItem) {
var date = new Date(dataItem.value);
if ((date.getDay() == 0 || date.getDay() == 6) && dateAxis.gridInterval.timeUnit == "day" && dateAxis.gridInterval.count == 1) {
dataItem.axisFill.visible = true;
}
else {
dataItem.axisFill.visible = false;
}
}
{
// ...
"xAxes": [{
// ...
"fillRule": function(dataItem) {
var date = new Date(dataItem.value);
if ((date.getDay() == 0 || date.getDay() == 6) && dateAxis.gridInterval.timeUnit == "day" && dateAxis.gridInterval.count == 1) {
dataItem.axisFill.visible = true;
}
else {
dataItem.axisFill.visible = false;
}
}
}]
}

There. Now the axis fills will be hidden if there are more data items than chart can display using daily grid. But it will go back to displaying them as soon as user zooms in enough.

See the Pen amCharts 4: Using fillRule by amCharts team (@amcharts) on CodePen.0

The above chart is also available in JSON version.