And because I couldn't stop myself! Here is an even better example that automatically creates both the canvas and the gauge if it doesn't yet exist and then updates it.
function createGauge(gaugeName, type, parent) {
// grab a reference to the HTML DOM element
let g = $(`#${gaugeName}`)
if (!g) { // if not found, append a new canvas element to the parent
let p = $(parent)
if (!p) p = $('body') // If parent not found, use body
let canvasEl = document.createElement('canvas')
canvasEl.id = gaugeName
p.append(canvasEl)
}
return new RadialGauge({
renderTo: gaugeName,
highlights: [
{ "from": 0, "to": 60, "color": "rgba(0,255,0)" },
{ "from": 60, "to": 80, "color": "rgba(255,255,0)" },
{ "from": 80, "to": 100, "color": "rgba(255,0,0)" }
],
width: 300,
height: 300,
units: "°C",
minValue: 0,
maxValue: 100,
majorTicks: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
minorTicks: 10,
strokeTicks: true,
colorPlate: "#fff",
borderShadowWidth: 0,
borders: false,
needleType: "arrow",
needleWidth: 2,
needleCircleSize: 7,
needlCircleOuter: true,
needleCircleInner: false,
animationDuration: 1500,
animationRule: "linear",
valueBox: true,
valueInt: 2,
valueDec: 2,
}).draw()
}
function updateGauge(msg, gauges) {
const gaugeName = msg.topic
// grab a reference to the HTML DOM element
const g = $(`#${gaugeName}`)
// If the element was actually found
if (g) {
if (msg.hide === true) {
g.style = 'display: none;'
} else {
g.style = 'display: initial;'
// assumes that `gauge1`, etc are global variables
gauges[msg.topic].value = msg.payload
gauges[msg.topic].update({
title: msg.topic
})
}
}
}
// Listen for incoming messages from Node-RED
uibuilder.onChange('msg', function (msg) {
// if the gauge doesn't exist, create it (Creates the canvas as well)
if (!gauges[msg.topic]) gauges[msg.topic] = createGauge(msg.topic, 'RadialGauge', 'body')
updateGauge(msg, gauges)
})
Obviously not low-code like using the msg._ui would be but fun anyway. A nice distraction at the end of a long day. I'll add the low code and this version to the WIKI when I get a chance.
PS: This isn't quite feature complete as it needs adjusting to allow for linear gauges and it should be updated to allow passing of the gauge properties to the create function. But hey! I'm not here to do everything.
What I really like about this example is that it demonstrates how little code is required to do amazing things with HTML (with a little help from Node-RED and uibuilder of course).