Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Controlling x-axis ticks on time series chart with chart.js

I'm creating a time series chart using Chart.js 4. Currently, it looks likes this: enter image description here but I only want the x-axis to be labeled every 15 seconds. So in this example, there would be 3 ticks, at 12:38:30, 12:38:45 and 12:39.
I've tried using stepSize and count, but neither seems to work.

This is my config

const config = {
    type: "line",
    data: {
        datasets: [{
            label: "20070480",
            borderColor: "#36A2EB",
            backgroundColor: "#9BD0F5",
            data: [
                [1681792679186, 1096],
                [1681792680186, 1147],
                [1681792681187, 1056],
                [1681792682187, 1100],
                [1681792683188, 1104],
                [1681792684188, 1158],
                [1681792685188, "1124.6319921491659"],
                [1681792686189, "1111.2244897959183"],
                [1681792687189, 1055.937193326791],
                [1681792688189, 1126.530612244898],
                [1681792689190, 1083.415112855741],
                [1681792690190, 1160],
                [1681792691190, "1068.3673469387754"],
                [1681792692191, "1094.2100098135427"],
                [1681792693191, 1159],
                [1681792694191, 1092],
                [1681792695192, 1115],
                [1681792696192, 1083],
                [1681792697192, 1146],
                [1681792698193, 1105],
                [1681792699193, 1085],
                [1681792700193, 1133],
                [1681792701194, 1101],
                [1681792702194, 1107],
                [1681792703195, 1074],
                [1681792704195, 1094],
                [1681792705195, 1126],
                [1681792706196, 1101],
                [1681792707196, 1065],
                [1681792708196, 1108],
                [1681792709197, 1125],
                [1681792710197, 1059],
                [1681792711198, 1186],
                [1681792712198, 1087],
                [1681792713198, 1117],
                [1681792714199, 1062],
                [1681792715199, 1118],
                [1681792716199, 1172],
                [1681792717200, 1148],
                [1681792718200, 1106],
                [1681792719201, 1061],
                [1681792720201, 1139],
                [1681792721201, 1114],
                [1681792722202, 1117],
                [1681792723202, 1123],
                [1681792724202, 1119],
                [1681792725203, 1119],
                [1681792726203, 1175],
                [1681792727204, 1089],
                [1681792728204, 1132],
                [1681792729204, "1130.5201177625124"],
                [1681792730205, "1161.2244897959183"],
                [1681792731205, 1085],
                [1681792732205, "1133.4641805691856"],
                [1681792733206, 1139],
                [1681792734206, 1147],
                [1681792735207, 1109],
                [1681792736207, "1152.0408163265306"],
                [1681792737207, "1087.3405299313054"],
                [1681792738208, 1145],
                [1681792739208, 1163],
                [1681792740208, 1061],
                [1681792741209, "1151.0204081632653"],
                [1681792742209, "1076.5456329735036"],
                [1681792743209, 1048],
                [1681792744210, 1117],
                [1681792745210, 1105],
                [1681792746210, 1103],
                [1681792747211, 1122],
                [1681792748211, 1105],
                [1681792749212, 1095],
                [1681792750212, 1141],
                [1681792751212, 1138],
                [1681792752212, 1160],
                [1681792753213, 1106],
                [1681792754213, 1077],
                [1681792755213, 1087],
                [1681792756214, 1138],
                [1681792757214, 1103],
                [1681792758215, 1114],
                [1681792759215, 1130],
                [1681792760215, 1128],
                [1681792761216, 1100],
                [1681792762216, 1068],
                [1681792763216, 1143],
                [1681792764217, 1142],
                [1681792765217, 1118],
                [1681792766218, 1089],
                [1681792767218, 1122],
                [1681792768218, 1122],
                [1681792769218, 1080],
                [1681792770219, 1182],
                [1681792771219, 1162],
                [1681792772220, 1100],
                [1681792773220, 1181],
                [1681792774220, 1103],
                [1681792775221, 1116],
                [1681792776221, 1095],
                [1681792777221, "1047.0588235294117"],
                [1681792778222, "1166.4964249233913"],
                [1681792779222, "1087.2549019607843"],
                [1681792780223, 1125],
                [1681792781223, 1060],
                [1681792782223, 1111],
                [1681792783224, 1057],
                [1681792784224, 1074],
                [1681792785224, "1141.9816138917263"],
                [1681792786225, 1104],
                [1681792787225, "1112.7450980392157"],
                [1681792788226, 1148],
                [1681792789226, 1146],
                [1681792790226, 1098],
                [1681792791227, 1164],
                [1681792792227, 1120],
                [1681792793227, 1144],
                [1681792794228, 1133],
                [1681792795228, 1163],
                [1681792796229, 1101],
                [1681792797229, 1108],
                [1681792798229, 1105]
            ]
        }]
    },

    options: {
        animation: false,
        scales: {
            x: {
                title: {
                    display: true,
                    text: "Time (UTC)",
                    font: {
                        size: 30,
                        weight: "bold"
                    }
                },
                type: "time",
                ticks: {
                    font: {
                        size: 20,
                        weight: "bold"
                    },
                    minRotation: 45,
                    count: 3,
                  //  stepSize: 15000,
                   // autoSkip: false
                },
                min: 1681792710000,
                max: 1681792740000
            },
            y: {
                title: {
                    display: true,
                    text: "Count Rate",
                    font: {
                        size: 30,
                        weight: "bold"
                    }
                },
                ticks: {
                    font: {
                        size: 15
                    }
                }
            }
        }
    }
};

P.S. Haven't had any luck creating a Codepen or JsFiddle using Chart.js 4.x, but you can use this playground, https://www.chartjs.org/docs/latest/samples/line/line.html and paste my config into there

like image 483
Peter Kronenberg Avatar asked Sep 13 '25 23:09

Peter Kronenberg


1 Answers

TLDR - use stepSize: 15; time axes use the concept of unit, that can be specified by the user as options.time.unit, see the docs. If not specified, the unit is computed from the data; in your case it's "second", but it's better to set it explicitly if you're using it - and you are, since the stepSize is computed in units not milliseconds.

const config = {
  type: "line",
  data: {
    datasets: [{
      label: "20070480",
      borderColor: "#36A2EB",
      backgroundColor: "#9BD0F5",
      data: [
        [1681792679186, 1096],
        [1681792680186, 1147],
        [1681792681187, 1056],
        [1681792682187, 1100],
        [1681792683188, 1104],
        [1681792684188, 1158],
        [1681792685188, "1124.6319921491659"],
        [1681792686189, "1111.2244897959183"],
        [1681792687189, 1055.937193326791],
        [1681792688189, 1126.530612244898],
        [1681792689190, 1083.415112855741],
        [1681792690190, 1160],
        [1681792691190, "1068.3673469387754"],
        [1681792692191, "1094.2100098135427"],
        [1681792693191, 1159],
        [1681792694191, 1092],
        [1681792695192, 1115],
        [1681792696192, 1083],
        [1681792697192, 1146],
        [1681792698193, 1105],
        [1681792699193, 1085],
        [1681792700193, 1133],
        [1681792701194, 1101],
        [1681792702194, 1107],
        [1681792703195, 1074],
        [1681792704195, 1094],
        [1681792705195, 1126],
        [1681792706196, 1101],
        [1681792707196, 1065],
        [1681792708196, 1108],
        [1681792709197, 1125],
        [1681792710197, 1059],
        [1681792711198, 1186],
        [1681792712198, 1087],
        [1681792713198, 1117],
        [1681792714199, 1062],
        [1681792715199, 1118],
        [1681792716199, 1172],
        [1681792717200, 1148],
        [1681792718200, 1106],
        [1681792719201, 1061],
        [1681792720201, 1139],
        [1681792721201, 1114],
        [1681792722202, 1117],
        [1681792723202, 1123],
        [1681792724202, 1119],
        [1681792725203, 1119],
        [1681792726203, 1175],
        [1681792727204, 1089],
        [1681792728204, 1132],
        [1681792729204, "1130.5201177625124"],
        [1681792730205, "1161.2244897959183"],
        [1681792731205, 1085],
        [1681792732205, "1133.4641805691856"],
        [1681792733206, 1139],
        [1681792734206, 1147],
        [1681792735207, 1109],
        [1681792736207, "1152.0408163265306"],
        [1681792737207, "1087.3405299313054"],
        [1681792738208, 1145],
        [1681792739208, 1163],
        [1681792740208, 1061],
        [1681792741209, "1151.0204081632653"],
        [1681792742209, "1076.5456329735036"],
        [1681792743209, 1048],
        [1681792744210, 1117],
        [1681792745210, 1105],
        [1681792746210, 1103],
        [1681792747211, 1122],
        [1681792748211, 1105],
        [1681792749212, 1095],
        [1681792750212, 1141],
        [1681792751212, 1138],
        [1681792752212, 1160],
        [1681792753213, 1106],
        [1681792754213, 1077],
        [1681792755213, 1087],
        [1681792756214, 1138],
        [1681792757214, 1103],
        [1681792758215, 1114],
        [1681792759215, 1130],
        [1681792760215, 1128],
        [1681792761216, 1100],
        [1681792762216, 1068],
        [1681792763216, 1143],
        [1681792764217, 1142],
        [1681792765217, 1118],
        [1681792766218, 1089],
        [1681792767218, 1122],
        [1681792768218, 1122],
        [1681792769218, 1080],
        [1681792770219, 1182],
        [1681792771219, 1162],
        [1681792772220, 1100],
        [1681792773220, 1181],
        [1681792774220, 1103],
        [1681792775221, 1116],
        [1681792776221, 1095],
        [1681792777221, "1047.0588235294117"],
        [1681792778222, "1166.4964249233913"],
        [1681792779222, "1087.2549019607843"],
        [1681792780223, 1125],
        [1681792781223, 1060],
        [1681792782223, 1111],
        [1681792783224, 1057],
        [1681792784224, 1074],
        [1681792785224, "1141.9816138917263"],
        [1681792786225, 1104],
        [1681792787225, "1112.7450980392157"],
        [1681792788226, 1148],
        [1681792789226, 1146],
        [1681792790226, 1098],
        [1681792791227, 1164],
        [1681792792227, 1120],
        [1681792793227, 1144],
        [1681792794228, 1133],
        [1681792795228, 1163],
        [1681792796229, 1101],
        [1681792797229, 1108],
        [1681792798229, 1105]
      ]
    }]
  },

  options: {
    animation: false,
    scales: {
      x: {
        title: {
          display: true,
          text: "Time (UTC)",
          font: {
            //size: 30,
            weight: "bold"
          }
        },
        type: "time",
        time: {
          //unit: "millisecond", // try this with stepsize 15000
          unit: "second" // that's the computed unit for this data
        },
        //beforeBuildTicks: function(ax){
        //   console.log(ax._unit);
        //},
        ticks: {
          font: {
            //size: 20,
            weight: "bold"
          },

          minRotation: 45,
          //count: 3,
          stepSize: 15,
          // autoSkip: false
        },
        min: 1681792710000,
        max: 1681792740000
      },
      y: {
        title: {
          display: true,
          text: "Count Rate",
          font: {
            //size: 30,
            weight: "bold"
          }
        },
        ticks: {
          font: {
           // size: 15
          }
        }
      }
    }
  }
};

new Chart(document.querySelector('#myChart'), config);
<div class="chart-container" style="width: 90vw">
    <canvas id="myChart"></canvas>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.3.0/chart.umd.min.js" integrity="sha512-TJ7U6JRJx5IpyvvO9atNnBzwJIoZDaQnQhb0Wmw32Rj5BQHAmJG16WzaJbDns2Wk5VG6gMt4MytZApZG47rCdg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-adapter-date-fns.bundle.min.js"></script>

The same in this fiddle

Now, the unit is relevant in the way the tick marks are rounded. In the code above I put under comments the variant unit: "millisecond"; you may use that and then you have to set stepSize: 15000 to get the three ticks, but then the text will be 7:38:30.000.

So, I guess that's the solution the authors of chart.js found to give a consistent approach to all things time-related, by replacing the hard javascript time unit of 1ms, with the more abstract unit that gives more control to the user. Note: don't experiment with unit: "minute" and stepSize: 0.25 - it gets into a nasty infinite loop :)

The variant where you set different tick formats for different units can be seen as "preventive": don't explicitly set the unit, let the code choose the optimal one from the data, and if it happens to be second use this format, and if it happens to be minute, use the other one, etc. It also makes sense with dynamic data, that comes from an external source, so the programmer might not know a priori what the appropriate unit will be.

like image 81
kikon Avatar answered Sep 15 '25 14:09

kikon