Embr-Charts Solutions Wiki

This topic has been created in wiki mode for collaborative generation of solutions to particular problems related to Musson Industrial's Embr-Charts module. To keep this neat, please follow these guidelines:

  • New problems seeking solutions should be posted as replies, and the discussion of that problem kept within that comment, wiki-style. A one-line summary should be added to this topic starter, with an embedded link (not on its own line). After posting, be sure to convert the comment to operate in wiki mode.

  • Use the "Hide Details" tool to keep the one comment neat. In particular, code blocks belong inside the details.

  • Create a "uses" details section at the end of a problem/solution comment where you deep link into the public module documentation for each function or feature used in the solution. Consider also deep linking into the IA manual, too.

Embr Module Downloads
Embr-Charts Documenation
About Musson Industrial

Topic Contents

Link your comments below here, as bullets, with a one-line description as the link text.

3 Likes

Show Day/Night Colour Banding

Source: Claude.ai, prompt: "chart.js. I want to show background colours on a line timeseries chart that shows different bg colours based on the time of day (night/day)"
Add a new array item under props.plugins and paste the below into the new item:

{
  "events": [
    "mousemove",
    "mouseout",
    "click",
    "touchstart",
    "touchmove"
  ],
  "id": "dayNightBackground",
  "beforeDatasetsDraw": "(chart) \u003d\u003e {\n    // Helper function to draw a time block\n    const drawTimeBlock \u003d (ctx, xScale, startTime, endTime, color, left, right, top, bottom) \u003d\u003e {\n        const startX \u003d Math.max(xScale.getPixelForValue(startTime.getTime()), left);\n        const endX \u003d Math.min(xScale.getPixelForValue(endTime.getTime()), right);\n\n        if (startX \u003c endX) {\n            ctx.fillStyle \u003d color;\n            ctx.fillRect(startX, top, endX - startX, bottom - top);\n        }\n    };\n    const {\n        ctx,\n        chartArea: {\n            top,\n            bottom,\n            left,\n            right\n        },\n        scales: {\n            x\n        }\n    } \u003d chart;\n\n    ctx.save();\n\n    // Get the time range\n    const minTime \u003d x.min;\n    const maxTime \u003d x.max;\n\n    // Iterate through each day in the range\n    let currentDate \u003d new Date(minTime);\n    currentDate.setHours(0, 0, 0, 0);\n\n    while (currentDate.getTime() \u003c maxTime) {\n        // Night period: 00:00 - 06:00\n        const nightStart \u003d new Date(currentDate);\n        nightStart.setHours(0, 0, 0, 0);\n        const nightEnd \u003d new Date(currentDate);\n        nightEnd.setHours(6, 0, 0, 0);\n\n        drawTimeBlock(ctx, x, nightStart, nightEnd, \u0027rgba(30, 58, 138, 0.1)\u0027, left, right, top, bottom);\n\n        // Day period: 06:00 - 18:00\n        const dayStart \u003d new Date(currentDate);\n        dayStart.setHours(6, 0, 0, 0);\n        const dayEnd \u003d new Date(currentDate);\n        dayEnd.setHours(18, 0, 0, 0);\n\n        drawTimeBlock(ctx, x, dayStart, dayEnd, \u0027rgba(252, 211, 77, 0.1)\u0027, left, right, top, bottom);\n\n        // Night period: 18:00 - 24:00\n        const eveningStart \u003d new Date(currentDate);\n        eveningStart.setHours(18, 0, 0, 0);\n        const eveningEnd \u003d new Date(currentDate);\n        eveningEnd.setHours(23, 59, 59, 999);\n\n        drawTimeBlock(ctx, x, eveningStart, eveningEnd, \u0027rgba(30, 58, 138, 0.1)\u0027, left, right, top, bottom);\n\n        // Move to next day\n        currentDate.setDate(currentDate.getDate() + 1);\n    }\n\n    ctx.restore();\n};\n"
}

Example (banded pale yellow / pale blue vertical bands):

PS. I'm showing the Source of where I derived the solution so that others like me who aren't javascript-fluent can see where I got my solution from! (I haven't written any more than 2% of the code myself)

1 Like

Show a Vertical Line on Hover

Source: Youtube
Add a new array item under props.plugins and paste the below into the new item.

{
  "events": [
    "mousemove",
    "mouseout",
    "click",
    "touchstart",
    "touchmove"
  ],
  "id": "verticalHoverLine",
  "beforeDatasetsDraw": "(chart, args, plugins) \u003d\u003e {\n    const { ctx, chartArea: { top, bottom, height } } \u003d chart;\n    \n    ctx.save();\n    chart.data.datasets.forEach((dataset, datasetIndex) \u003d\u003e {\n      chart.getDatasetMeta(datasetIndex).data.forEach((dataPoint, index) \u003d\u003e {\n        if(dataPoint.active \u003d\u003d\u003d true) {\n        \n          ctx.beginPath();\n          ctx.strokeStyle \u003d \u0027orange\u0027;\n          ctx.moveTo(dataPoint.x, top);\n          ctx.lineTo(dataPoint.x, bottom);\n          ctx.stroke();\n        }\n      });\n  });\n  }"
}

Example (orange vertical line):


Change the colour of the y-axis zero line

Source: Claude.ai, prompt: "chart.js. how to set the zero line style for the y axis?"
To change the colour of the zero line, under props.options.scales.y.grid.color, paste the below:

(context) => {
   if (context.tick.value === 0) {
      return 'hsla(0, 80%, 50%, 0.4)';
   }
   return 'hsla(0, 0%, 0%, 0.2)';
}

To change the stroke width, under props.options.scales.y.grid.lineWidth, paste the below:

(context) => {
   if (context.tick.value === 0) {
      return 2;
   }
   return 1;
}

Example (red 2px width zero line):


Change the date format of the data point tooltips

Source: Claude.ai
Under props.options.plugins.tooltip add a callbacks object. Add a title key into the callbacks object and paste this below.

  • I'm forcing to 'sv-SE' locale to use the date format: YYYY-MM-dd HH:mm:ss Z.
    Change this to [] to (supposedly) use the client's locale (I didn't find this worked as my browser reports en-AU but using [] was still messing up the date into reverse-shuffled triangle date format (MM/DD/YYYY :stuck_out_tongue: ) so I had to force it to unshuffle it by supplying the locale myself.
  • I'm also forcing it to show the timezone in Australia/Brisbane as that's what the client needs it in for electricity prices.
(context) => {
  const d = new Date(context[0].raw.x);
  const formattedDate = d.toLocaleString('sv-SE', {
   year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    hour12: false,
    minute: '2-digit',
    second: '2-digit',
    timeZoneName: 'longOffset',
    timeZone: 'Australia/Brisbane'
  });
  return formattedDate;
};

Example:
image

1 Like