javascriptdatetimechart.jsmomentjs

How to use string time data with moment.js in Chartjs


I have an array of lap times as strings shown below:

['00:01:41.413000', '00:01:38.790000', '00:01:38.917000', '00:01:38.470000', '00:01:37.906000', '00:01:37.997000', '00:01:37.774000', '00:01:37.669000', '00:01:37.890000', '00:01:37.739000', '00:01:37.593000', '00:01:37.778000', '00:01:37.701000', '00:01:37.707000', '00:01:37.826000', '00:01:37.851000', '00:01:37.987000', '00:01:38.068000', '00:01:38.017000', '00:01:38.123000', '00:01:38.172000', '00:01:38.192000', '00:01:38.231000', '00:01:38.399000', '00:01:38.641000', '00:01:38.575000', '00:01:38.927000', '00:01:39.265000', '00:01:47.873000', '00:01:58.989000', '00:01:36.688000', '00:01:36.824000', '00:01:37.022000', '00:01:36.871000', '00:01:37.100000', '00:01:36.968000', '00:01:36.984000', '00:01:37.071000', '00:01:36.957000', '00:01:36.962000', '00:01:37.380000', '00:01:36.865000', '00:01:36.582000', '00:01:36.414000', '00:01:36.618000', '00:01:36.500000', '00:01:36.628000', '00:01:36.739000', '00:01:36.602000', '00:01:37.055000', '00:01:37.132000', '00:01:36.842000', '00:01:36.843000', '00:01:36.748000', '00:01:36.427000', '00:01:36.387000', '00:01:36.402000', '00:01:36.171000', '00:01:35.967000', '00:01:36.343000', '00:01:36.013000', '00:01:36.931000']

I want to use Chart.js and moment.js to use this data as the graph data for a linear chart, without having to convert it to milliseconds etc. I want the format for the data to be "mm:ss.SSS" on the graph. I have no idea how to do this using moment and the time cartesian parsers in Chart.js

The only relevant resources I could find were outdated versions of Chartjs. I have tried converting the strings into moments of milliseconds and setting:

time: {
  parser: "mm:ss.SSS",
  unitStepSize: 5,

  displayFormats: {
    seconds: "m.s",
   },
},

on the y-axis which displays the data but with 0:00 across the axis. My full chart without the time parser is below:

  new Chart(ctx, {
    type: "line",
    data: {
      // Generates an array from 1 to total laps to label the axis
      labels: Array.from({ length: totalLaps }, (_, i) => i + 1),
      datasets: datasets,
    },
    options: {
      scales: {
        x: {
          title: {
            display: true,
            text: "Lap number",
            padding: {
              top: 24,
            },
          },
        },
        y: {
          title: {
            display: true,
            text: "Lap time",
            padding: {
              bottom: 24,
            },
          },
        },
      },

      // Styles the tooltip hover

      plugins: {
        tooltip: {
          enabled: true,
          backgroundColor: "rgba(0, 0, 0, 0.7)",
          titleColor: "#ffffff",
          borderColor: "rgba(255, 255, 255, 0.5)",
          borderWidth: 1,
          padding: 16,

          titleFont: {
            size: 16,
          },
          bodyFont: {
            size: 16,
          },

          titleAlign: "center",
          titleMarginBottom: 8,
          cornerRadius: 8,
          displayColors: false,

          useHTML: true,

          callbacks: {
            title: (tooltipItems) => `Lap ${tooltipItems[0].label}`,
            label: (tooltipItem) => {
              const dataset = datasets[tooltipItem.datasetIndex];
              const value = tooltipItem.raw;

              const lapCompound = dataset.laps[tooltipItem.dataIndex][1];

              return `${dataset.label}: ${value} [${lapCompound}]`;
            },
          },
        },
      },
    },
  });```

Solution

  • Maybe you do need to convert to ms, but only format it as mm:ss.SSS for display purposes. To format the ticks you can use the ticks.callback option (docs). To format the tooltips you can use similar approach using callbacks.label option (docs)

    The result should look like:

    function timeToMs(timeString) {
      // convert time string to ms
      // use AI for code
    }
    
    function formatMs(ms) {
      // convert ms to mm:ss:SSS
      // use AI for code
    }
    
    
    new Chart(ctx, {
      type: "line",
      data: {
        // ...
      },
      options: {
        scales: {
          y: {
            ticks: {
              callback: function(value) {
                return formatMs(value);
              }
            }
          },
        },
        plugins: {
          tooltip: {
            callbacks: {
              label: function(context) {
                return `${formatMs(context.parsed.y)}`;
              }
            }
          }
        }
      },
    });