Wildly Misusing the Canvas Gauge for Arbitrary Tickmarks

Background

So I just got one of those analogue lab incubators you might remember from high school, and want to use it to ferment things. I’ve been testing the different gas marks (it’s electric but that’s all i can think to call them, since it’s analog? idk) to see what temperature they correspond to. I decided I wanted a visual representation on my dashboard of what temperature the bluetooth thermometer I put inside was reading. This could technically be a static image but where’s the fun in that?

Anyway, the canvas gauge card [as of v0.4.1] allows EITHER string labels equally spaced throughout the gauge range OR numerical labels correctly labeling the gauge. But what if you want to place arbitrary labels at arbitrary values?

WELL it turns out that you can pass arrays to specify the name, label color, and tick color, and “transparent” is a valid color

So, with the help of the config template card’s javascript functionality to keep you from having to write out a hundred-entry long list, it turns out you can do just that!

YAML below.

NOTE: the reason i have different functions for dealing with an array of colors vs an array of labels instead of just having the choice to fill hidden values with '' or 'transparent' be another input is that the card/canvasgauge project has a bug where the gauge border will be the same color as the first of the ticks, so you gotta inject a black one at the beginning of the array or it’ll give you a transparent ring instead. Haven’t checked if separately specifying the gauge border color would fix it, that’s not really relevant to this project

NOTE 2: Javascript isn’t my main programming language, so i’m sure this could be written better. If you don’t like it, write a better one

type: custom:config-template-card
variables:
  TEMPERATURE: states['sensor.ble_temperature_cc3238313892'].state
  _scaleMin: 0
  _scaleMax: 100
  tickLocations:
    - 12
    - 22
    - 70
    - 92.7
  tickNames: ['99','nope','3','what'] //you can use javascript arrays as well but unfortunately line breaks still don't work
  tickColors:
    - 'red'
    - 'purple'
    - 'blue'
    - 'green'
  nameArray: |
    (nameArray, locArray, gaugeMin, gaugeMax) => {
        // nameArray and locArray must be the same length
        // gaugeMin and gaugeMax should be integers or floats
        var labelArray = locArray.map(function(e, i) {
          return [e, nameArray[i]];
        });
        var limits = +((gaugeMax - gaugeMin).toFixed(1));
        limits *= 10 //allows us to have 1 decimal of precision
        let arr = new Array(parseInt(limits));
        arr.fill("")
        labelArray.forEach(function (item) {
            arr[10*(item[0]-gaugeMin)]=item[1];
        });
        return arr;
      }
  colorArray: |
    (nameArray, locArray, gaugeMin, gaugeMax) => {
       // nameArray and locArray must be the same length
       // gaugeMin and gaugeMax should be integers or floats
       var labelArray = locArray.map(function(e, i) {
         return [e, nameArray[i]];
       });
       var limits = +((gaugeMax - gaugeMin).toFixed(1));
       limits *= 10 //allows us to have 1 decimal of precision
       let arr = new Array(parseInt(limits));
       arr.fill("transparent")
       labelArray.forEach(function (item) {
           arr[(10*item[0])-(10*gaugeMin)]=item[1];
       });
       arr[0]="black";
       arr[arr.length - 1]="black";
       return arr;
     }
entities:
  - sensor.ble_temperature_cc3238313892
card:
  type: custom:mod-card
  card:
    type: custom:canvas-gauge-card
    entity: sensor.ble_temperature_cc3238313892
    card_height: 125
    gauge:
      type: radial-gauge
      title: null
      width: 220
      height: 125
      minValue: ${_scaleMin}
      maxValue: ${_scaleMax}
      valueBox: false
      fontNumbersSize: 30
      valueDec: 1
      valueText: ${TEMPERATURE.toString()+'°'+'F'}
      majorTicks: ${ nameArray(tickNames,tickLocations,_scaleMin,_scaleMax) }
      colorMajorTicks: ${ colorArray(tickColors,tickLocations,_scaleMin,_scaleMax) }
      colorNumbers: ${ colorArray(tickColors,tickLocations,_scaleMin,_scaleMax)}
      minorTicks: null
      strokeTicks: true
      animation: false
      highlightsLineCap: round
      highlights:
        - from: 42
          to: 53
          color: orange
        - from: 75.2
          to: ${_scaleMax}
          color: pink
      borders: false
  card_mod:
    style: |
      canvas-gauge-card {
        box-shadow: none !important;
        background: none !important;
        }
2 Likes

Hi,

Would you happen to know how to use the fontNumbers and the fontNumbersStyle options.

Ive tried everything and just cant seem to get it to apply.

https://fonts.googleapis.com/css?family=Comfortaa&display=swap

Thanks for the hint with the transparent “colorNumber”! Quite an old topic, but it solved my current problem to create ticks without labels.

In the following example I used quite a simple workaround without using JS to “ink-out” the 1500, 2500 and 3500 tick labels while keeping the ticks itself:

  maxValue: 5000
  exactTicks: true
  majorTicks:
    - 5000 # black
    - 4600 # black
    - 4000 # black
    - 3500 # transparent
    - 3000 # black
    - 2500 # transparent
    - 2000 # black
    - 1500 # transparent
    - 1000 # black
    - 500  # black
    - 0    # black
  colorNumbers:
    - black
    - black
    - black
    - transparent
    - black
    - transparent
    - black
    - transparent
    - black
    - black
    - black
  minorTicks: 100