Faire des jauges de ce type

Houlà Bob, ferme la fenêtre du salon, tu as oublié que tu étais dans le Morbihan ??? 71% d’humidité, tu veux faire pousser du riz ? :grin:

2 « J'aime »

Si j’ouvre ce sera pire @btncrd :rofl:


Je chauffe peu, je passe peu de temps chez moi l’hiver, mais 16°C c’est confort :hugs:

Bob

Il est passé où le micro-climat entre Lorient et Vannes ??? On se croirait dans le Finistère là :rofl:

Nous remplissons les nappes phréatiques encore quelques jours avant les premiers flocons :wink:
Dans le Finistère dont je suis originaire ce qui est bien c’est qu’il ne pleut que la nuit, non je ne suis pas chauvin :laughing:
Bob

On est pareil, alors que je suis dans le sud

Deux jours que je chauffe pas, c’est le sauna à la maison. :rofl:

Le code pour la jauge CO2 :

type: custom:button-card
entity: input_number.ppm
show_state: false
show_icon: false
show_name: false
tap_action: none
double_tap_action: none
hold_action: none
custom_fields:
  icon:
    card:
      type: custom:button-card
      icon: mdi:molecule-co2
      styles:
        card:
          - aspect-ratio: 1/1
          - width: 50px
          - padding: 0
          - border: 4px dashed white
          - border-radius: 50%
          - background: none
        icon:
          - width: 90%
          - color: white
  name:
    card:
      type: custom:button-card
      name: Niveau de CO<sub style="font-size:1.0rem;">2</sub> intérieur
      styles:
        card:
          - width: 300px
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.4rem
          - align-self: start
          - justify-self: start
          - color: white
          - font-weight: 500
  value:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: true
      state_display: |
        [[[
          return parseFloat(entity.state).toFixed(0);
        ]]]
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        state:
          - color: white
          - font-size: 2.5rem
          - font-weight: 800
  unit:
    card:
      type: custom:button-card
      name: ppm
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.4rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 800
  min_val:
    card:
      type: custom:button-card
      name: "400"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.0rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  max_val:
    card:
      type: custom:button-card
      name: "2000"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.0rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  bar:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - height: 12px
          - width: 380px
          - border-radius: 999px
          - border: 0
          - padding: 0px
          - background: >-
              linear-gradient(to right, rgba(0,255,24,1.0) 0%,
              rgba(152,255,0,1.0) 40%, rgba(255,252,0,1.0) 55%,
              rgba(255,174,0,1.0) 75%, rgba(255,0,0,1.0) 100%)
  cursor:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - width: 16px
          - height: 32px
          - border-radius: 999px
          - border: 4px solid rgba(42,45,54,1.0)
          - background-color: |
              [[[
                const ppm = Number(entity.state) || 0;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0,   255, 24]  },
                  { p: 40,  c: [152, 255, 0]   },
                  { p: 55,  c: [255, 252, 0]   },
                  { p: 75,  c: [255, 174, 0]   },
                  { p: 100, c: [255, 0,   0]   }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},1.0)`;
              ]]]
  comment:
    card:
      type: custom:button-card
      show_name: true
      show_icon: false
      show_state: false
      name: |
        [[[
          const ppm = Number(entity.state) || 0;
          if (ppm < 900) {
            return "Excellent";
          }
          if (ppm >= 900 && ppm <= 1150) {
            return "Bon";
          }
          if (ppm >= 1151 && ppm <= 1400) {
            return "Acceptable";
          }
          if (ppm >= 1401 && ppm <= 1600) {
            return "Mauvais";
          }
          if (ppm > 1600) {
            return "Malsain";
          }
        ]]]
      styles:
        card:
          - height: 12px
          - width: auto
          - height: 36px
          - border-radius: 999px
          - border: 0
          - padding: 20px
          - background: white
          - background-color: |
              [[[
                const ppm = Number(entity.state) || 0;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0,   255, 24]  },
                  { p: 40,  c: [152, 255, 0]   },
                  { p: 55,  c: [255, 252, 0]   },
                  { p: 75,  c: [255, 174, 0]   },
                  { p: 100, c: [255, 0,   0]   }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},0.5)`;
              ]]]
        name:
          - font-size: 1.4rem
          - font-weight: 600
          - color: |
              [[[
                const ppm = Number(entity.state) || 0;
                if (ppm < 900) {
                  return "rgba(0,255,24,1.0)";
                }
                if (ppm >= 900 && ppm <= 1150) {
                  return "rgba(152,255,0,1.0)";
                }
                if (ppm >= 1151 && ppm <= 1400) {
                  return "rgba(255,252,0,1.0)";
                }
                if (ppm >= 1401 && ppm <= 1600) {
                  return "rgba(255,174,0,1.0)";
                }
                if (ppm > 1600) {
                  return "rgba(255,113,0,1.0)";
                }
              ]]]
styles:
  card:
    - background-color: rgba(42,45,54,1.0)
    - aspect-ratio: 2/1
    - cursor: default
  custom_fields:
    icon:
      - position: absolute
      - top: 3%
      - left: 1%
    name:
      - position: absolute
      - top: 10%
      - left: 15%
    value:
      - position: absolute
      - top: 46%
      - right: 50%
      - margin-right: 1%
      - transform: translateY(-50%)
    unit:
      - position: absolute
      - left: 50%
      - top: 48%
      - margin-left: 1%
      - transform: translateY(-50%)
    min_val:
      - position: absolute
      - bottom: 28%
      - left: 9%
    max_val:
      - position: absolute
      - bottom: 28%
      - right: 9%
    comment:
      - position: absolute
      - left: 50%
      - top: 80%
      - transform: translate(-50%, -50%)
    bar:
      - position: absolute
      - left: 50%
      - top: 60%
      - transform: translate(-50%, -50%)
    cursor:
      - position: absolute
      - top: "[[[ return 'calc(60% - 16px)'; ]]]"
      - left: |
          [[[
            const ppm = Number(entity.state) || 0;
            const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
            const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
            const barWidth = 380;
            const halfCursor = 8;
            const offsetPx = (barWidth * percent) / 100;
            return `calc(50% - ${barWidth/2}px + ${offsetPx}px - ${halfCursor}px)`;
          ]]]

Il y a encore des choses améliorables : actuellement la valeur chiffrée est centrée sur la carte, en réduisant un peu la taille de la police, je peux la placer automatiquement pile au dessus du curseur. Je peux mettre une barre (trait) entre le nom et la jauge, etc.

Là en revanche, il me faut du visuel pour comprendre ce que tu veux

1 « J'aime »

Presque, il manque le trait de séparation :rofl:

C’est de ça dont je parlais @WarC0zes :wink:

type: custom:button-card
entity: input_number.ppm
show_state: false
show_icon: false
show_name: false
tap_action: none
double_tap_action: none
hold_action: none
custom_fields:
  icon:
    card:
      type: custom:button-card
      icon: mdi:molecule-co2
      styles:
        card:
          - aspect-ratio: 1/1
          - width: 50px
          - padding: 0
          - border: 4px dashed white
          - border-radius: 50%
          - background: none
        icon:
          - width: 90%
          - color: white
  name:
    card:
      type: custom:button-card
      name: Niveau de CO<sub style="font-size:1.0rem;">2</sub> intérieur
      styles:
        card:
          - width: 300px
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.4rem
          - align-self: start
          - justify-self: start
          - color: white
          - font-weight: 500
  separation:
    card:
      type: custom:button-card
      styles:
        card:
          - width: 600px
          - height: 1px
          - padding: 0
          - border: 1px solid rgba(54,56,68,1.0)
          - border-radius: 0
          - background: none
  value:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: true
      state_display: |
        [[[
          return parseFloat(entity.state).toFixed(0);
        ]]]
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        state:
          - color: white
          - font-size: 2.5rem
          - font-weight: 800
  unit:
    card:
      type: custom:button-card
      name: ppm
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.4rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 800
  min_val:
    card:
      type: custom:button-card
      name: "400"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.0rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  max_val:
    card:
      type: custom:button-card
      name: "2000"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.0rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  bar:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - height: 12px
          - width: 380px
          - border-radius: 999px
          - border: 0
          - padding: 0px
          - background: >-
              linear-gradient(to right, rgba(0,255,24,1.0) 0%,
              rgba(152,255,0,1.0) 40%, rgba(255,252,0,1.0) 55%,
              rgba(255,174,0,1.0) 75%, rgba(255,0,0,1.0) 100%)
  cursor:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - width: 16px
          - height: 32px
          - border-radius: 999px
          - border: 4px solid rgba(42,45,54,1.0)
          - background-color: |
              [[[
                const ppm = Number(entity.state) || 0;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0,   255, 24]  },
                  { p: 40,  c: [152, 255, 0]   },
                  { p: 55,  c: [255, 252, 0]   },
                  { p: 75,  c: [255, 174, 0]   },
                  { p: 100, c: [255, 0,   0]   }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},1.0)`;
              ]]]
  comment:
    card:
      type: custom:button-card
      show_name: true
      show_icon: false
      show_state: false
      name: |
        [[[
          const ppm = Number(entity.state) || 0;
          if (ppm < 900) {
            return "Excellent";
          }
          if (ppm >= 900 && ppm <= 1150) {
            return "Bon";
          }
          if (ppm >= 1151 && ppm <= 1400) {
            return "Acceptable";
          }
          if (ppm >= 1401 && ppm <= 1600) {
            return "Mauvais";
          }
          if (ppm > 1600) {
            return "Malsain";
          }
        ]]]
      styles:
        card:
          - height: 12px
          - width: auto
          - height: 36px
          - border-radius: 999px
          - border: 0
          - padding: 20px
          - background: white
          - background-color: |
              [[[
                const ppm = Number(entity.state) || 0;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0,   255, 24]  },
                  { p: 40,  c: [152, 255, 0]   },
                  { p: 55,  c: [255, 252, 0]   },
                  { p: 75,  c: [255, 174, 0]   },
                  { p: 100, c: [255, 0,   0]   }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},0.5)`;
              ]]]
        name:
          - font-size: 1.4rem
          - font-weight: 600
          - color: |
              [[[
                const ppm = Number(entity.state) || 0;
                if (ppm < 900) {
                  return "rgba(0,255,24,1.0)";
                }
                if (ppm >= 900 && ppm <= 1150) {
                  return "rgba(152,255,0,1.0)";
                }
                if (ppm >= 1151 && ppm <= 1400) {
                  return "rgba(255,252,0,1.0)";
                }
                if (ppm >= 1401 && ppm <= 1600) {
                  return "rgba(255,174,0,1.0)";
                }
                if (ppm > 1600) {
                  return "rgba(255,113,0,1.0)";
                }
              ]]]
styles:
  card:
    - background-color: rgba(42,45,54,1.0)
    - aspect-ratio: 2/1
    - cursor: default
  custom_fields:
    icon:
      - position: absolute
      - top: 3%
      - left: 1%
    name:
      - position: absolute
      - top: 10%
      - left: 15%
    separation:
      - position: absolute
      - top: 30%
      - left: 0%
    value:
      - position: absolute
      - top: 46%
      - right: 50%
      - margin-right: 1%
      - transform: translateY(-50%)
    unit:
      - position: absolute
      - left: 50%
      - top: 48%
      - margin-left: 1%
      - transform: translateY(-50%)
    min_val:
      - position: absolute
      - bottom: 28%
      - left: 9%
    max_val:
      - position: absolute
      - bottom: 28%
      - right: 9%
    comment:
      - position: absolute
      - left: 50%
      - top: 80%
      - transform: translate(-50%, -50%)
    bar:
      - position: absolute
      - left: 50%
      - top: 60%
      - transform: translate(-50%, -50%)
    cursor:
      - position: absolute
      - top: "[[[ return 'calc(60% - 16px)'; ]]]"
      - left: |
          [[[
            const ppm = Number(entity.state) || 0;
            const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
            const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
            const barWidth = 380;
            const halfCursor = 8;
            const offsetPx = (barWidth * percent) / 100;
            return `calc(50% - ${barWidth/2}px + ${offsetPx}px - ${halfCursor}px)`;
          ]]]

J’en ai profité pour changer la couleur de bordure du « cursor » qui avait disparue et du coup apparaissait en noir.

2 « J'aime »

N’oublies pas de préciser que la nuit dure 20 heures en hiver et 18 heures en été dans le Finistère :rofl:
En fait j’exagère, comme il n’y a que 2 saisons dans le Finistère (l’automne et le 15 août), le 15 août, la nuit ne dure que 12 heures (et 18 heures pour l’automne) :wink:

c’est top tout ça, je vais regarder et essayer de comprendre merci beaucoup

Dans le Finistère nous sommes les derniers à voir le soleil se coucher, sur la mer, le matin, rien ne presse pour se lever :slight_smile:
Bob

1 « J'aime »

J’ai cet affichage, je pense qu’il va falloir que je réduise

Bonjour,
Oui il faut que tu réduise la taille de la « bar » mais aussi la valeur de const barWidth = 380
Il faudra mettre à la place de 380 la valeur de largeur de la « bar », le bloc ci-dessous est ce qui permet de définir la position du « cursor » sur la « bar » :

    cursor:
      - position: absolute
      - top: "[[[ return 'calc(60% - 16px)'; ]]]"
      - left: |
          [[[
            const ppm = Number(entity.state) || 0;
            const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
            const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
            const barWidth = 380;
            const halfCursor = 8;
            const offsetPx = (barWidth * percent) / 100;
            return `calc(50% - ${barWidth/2}px + ${offsetPx}px - ${halfCursor}px)`;
          ]]]

J’approche de ce que j’ai besoin :

Il faut que j’identifie la taille du commentaire et du fond encore :

type: custom:button-card
entity: sensor.netatmo_salon_dioxyde_de_carbone
show_state: false
show_icon: false
show_name: false
tap_action: none
double_tap_action: none
hold_action: none
custom_fields:
  icon:
    card:
      type: custom:button-card
      icon: mdi:molecule-co2
      styles:
        card:
          - aspect-ratio: 1/1
          - width: 20px
          - padding: 0
          - border: 1px dashed white
          - border-radius: 50%
          - background: none
        icon:
          - width: 90%
          - color: white
  name:
    card:
      type: custom:button-card
      name: Niveau de CO<sub style="font-size:1.0rem;">2</sub> intérieur
      styles:
        card:
          - width: 300px
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.4rem
          - align-self: start
          - justify-self: start
          - color: white
          - font-weight: 100
  separation:
    card:
      type: custom:button-card
      styles:
        card:
          - width: 600px
          - height: 1px
          - padding: 0
          - border: 1px solid rgba(54,56,68,1.0)
          - border-radius: 0
          - background: none
  value:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: true
      state_display: |
        [[[
          return parseFloat(entity.state).toFixed(0);
        ]]]
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        state:
          - color: white
          - font-size: 2.5rem
          - font-weight: 800
  unit:
    card:
      type: custom:button-card
      name: ppm
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.4rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 800
  min_val:
    card:
      type: custom:button-card
      name: "400"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.0rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  max_val:
    card:
      type: custom:button-card
      name: "2000"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.0rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  bar:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - height: 8px
          - width: 330px
          - border-radius: 999px
          - border: 0
          - padding: 0px
          - background: >-
              linear-gradient(to right, rgba(0,255,24,1.0) 0%,
              rgba(152,255,0,1.0) 40%, rgba(255,252,0,1.0) 55%,
              rgba(255,174,0,1.0) 75%, rgba(255,0,0,1.0) 100%)
  cursor:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - width: 14px
          - height: 32px
          - border-radius: 999px
          - border: 4px solid rgba(42,45,54,1.0)
          - background-color: |
              [[[
                const ppm = Number(entity.state) || 0;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0,   255, 24]  },
                  { p: 40,  c: [152, 255, 0]   },
                  { p: 55,  c: [255, 252, 0]   },
                  { p: 75,  c: [255, 174, 0]   },
                  { p: 100, c: [255, 0,   0]   }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},1.0)`;
              ]]]
  comment:
    card:
      type: custom:button-card
      show_name: true
      show_icon: false
      show_state: false
      name: |
        [[[
          const ppm = Number(entity.state) || 0;
          if (ppm < 900) {
            return "Excellent";
          }
          if (ppm >= 900 && ppm <= 1150) {
            return "Bon";
          }
          if (ppm >= 1151 && ppm <= 1400) {
            return "Acceptable";
          }
          if (ppm >= 1401 && ppm <= 1600) {
            return "Mauvais";
          }
          if (ppm > 1600) {
            return "Malsain";
          }
        ]]]
      styles:
        card:
          - height: 12px
          - width: auto
          - height: 36px
          - border-radius: 999px
          - border: 0
          - padding: 20px
          - background: white
          - background-color: |
              [[[
                const ppm = Number(entity.state) || 0;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0,   255, 24]  },
                  { p: 40,  c: [152, 255, 0]   },
                  { p: 55,  c: [255, 252, 0]   },
                  { p: 75,  c: [255, 174, 0]   },
                  { p: 100, c: [255, 0,   0]   }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},0.5)`;
              ]]]
        name:
          - font-size: 1.4rem
          - font-weight: 600
          - color: |
              [[[
                const ppm = Number(entity.state) || 0;
                if (ppm < 900) {
                  return "rgba(0,255,24,1.0)";
                }
                if (ppm >= 900 && ppm <= 1150) {
                  return "rgba(152,255,0,1.0)";
                }
                if (ppm >= 1151 && ppm <= 1400) {
                  return "rgba(255,252,0,1.0)";
                }
                if (ppm >= 1401 && ppm <= 1600) {
                  return "rgba(255,174,0,1.0)";
                }
                if (ppm > 1600) {
                  return "rgba(255,113,0,1.0)";
                }
              ]]]
styles:
  card:
    - background-color: rgba(42,45,54,1.0)
    - aspect-ratio: 2/1
    - cursor: default
  custom_fields:
    icon:
      - position: absolute
      - top: 3%
      - left: 1%
    name:
      - position: absolute
      - top: 3%
      - left: 8%
    separation:
      - position: absolute
      - top: 17%
      - left: 0%
    value:
      - position: absolute
      - top: 30%
      - right: 50%
      - margin-right: 1%
      - transform: translateY(-50%)
    unit:
      - position: absolute
      - left: 50%
      - top: 27%
      - margin-left: 1%
      - transform: translateY(-50%)
    min_val:
      - position: absolute
      - top: 53%
      - left: 2%
    max_val:
      - position: absolute
      - top: 53%
      - right: 2%
    comment:
      - position: absolute
      - left: 50%
      - top: 68%
      - transform: translate(-50%, -50%)
    bar:
      - position: absolute
      - left: 50%
      - top: 45%
      - transform: translate(-50%, -50%)
    cursor:
      - position: absolute
      - top: "[[[ return 'calc(45% - 16px)'; ]]]"
      - left: |
          [[[
            const ppm = Number(entity.state) || 0;
            const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
            const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
            const barWidth = 330;
            const halfCursor = 8;
            const offsetPx = (barWidth * percent) / 100;
            return `calc(50% - ${barWidth/2}px + ${offsetPx}px - ${halfCursor}px)`;
          ]]]
![1000114870|358x500](upload://5Oz29hMvsrxdzDPwxTkopRDAbiv.jpeg)

Il faudrait que je trouve les valeurs pour les autres capteurs

La taille (largeur) du commentaire (« comment ») s’adapte automatiquement à son contenu avec un padding droit et gauche de 20px (espacement entre les bords droit et gauche du custom_fields et son contenu)

  comment:
    card:
      type: custom:button-card
      show_name: true
      show_icon: false
      show_state: false
      name: |
        [[[
          const ppm = Number(entity.state) || 0;
          if (ppm < 900) {
            return "Excellent";
          }
          if (ppm >= 900 && ppm <= 1150) {
            return "Bon";
          }
          if (ppm >= 1151 && ppm <= 1400) {
            return "Acceptable";
          }
          if (ppm >= 1401 && ppm <= 1600) {
            return "Mauvais";
          }
          if (ppm > 1600) {
            return "Malsain";
          }
        ]]]
      styles:
        card:
          - height: 12px
          - width: auto
          - height: 36px                <------- hauteur du custom_fields
          - border-radius: 999px
          - border: 0
          - padding: 20px           <------- padding global : les dimensions du custom_fields gardent un espace de 20 pixels par rapports aux bords de celui-ci
          - background: white
          - background-color: |
              [[[
                const ppm = Number(entity.state) || 0;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0,   255, 24]  },
                  { p: 40,  c: [152, 255, 0]   },
                  { p: 55,  c: [255, 252, 0]   },
                  { p: 75,  c: [255, 174, 0]   },
                  { p: 100, c: [255, 0,   0]   }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},0.5)`;
              ]]]
        name:
          - font-size: 1.4rem     <------ permet d'augmenter ou diminuer la taille de la police
          - font-weight: 600
          - color: |
              [[[
                const ppm = Number(entity.state) || 0;
                if (ppm < 900) {
                  return "rgba(0,255,24,1.0)";
                }
                if (ppm >= 900 && ppm <= 1150) {
                  return "rgba(152,255,0,1.0)";
                }
                if (ppm >= 1151 && ppm <= 1400) {
                  return "rgba(255,252,0,1.0)";
                }
                if (ppm >= 1401 && ppm <= 1600) {
                  return "rgba(255,174,0,1.0)";
                }
                if (ppm > 1600) {
                  return "rgba(255,113,0,1.0)";
                }
              ]]]


ci-dessus un exemple avec un padding adapté pour les 4 côtés, une hauteur et une largeur du custom_fields en auto et une taille de police réduite.

Voici des infos pour la température et l’humidité :wink: je regarde ta réponse ce soir. Merci beaucoup

J’avance petit à petit, maintenant il faudrait que je puisse réduire en hauteur la carte du fond pour avoir moins d’espace en bas

type: custom:button-card
entity: sensor.netatmo_salon_dioxyde_de_carbone
show_state: false
show_icon: false
show_name: false
tap_action: none
double_tap_action: none
hold_action: none
custom_fields:
  icon:
    card:
      type: custom:button-card
      icon: mdi:molecule-co2
      styles:
        card:
          - aspect-ratio: 1/1
          - width: 20px
          - padding: 0
          - border: 1px dashed white
          - border-radius: 50%
          - background: none
        icon:
          - width: 90%
          - color: white
  name:
    card:
      type: custom:button-card
      name: Niveau de CO<sub style="font-size:1.0rem;">2</sub> intérieur
      styles:
        card:
          - width: 300px
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.4rem
          - align-self: start
          - justify-self: start
          - color: white
          - font-weight: 100
  separation:
    card:
      type: custom:button-card
      styles:
        card:
          - width: 600px
          - height: 1px
          - padding: 0
          - border: 1px solid rgba(54,56,68,1.0)
          - border-radius: 0
          - background: none
  value:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: true
      state_display: |
        [[[
          return parseFloat(entity.state).toFixed(0);
        ]]]
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        state:
          - color: white
          - font-size: 2.5rem
          - font-weight: 800
  unit:
    card:
      type: custom:button-card
      name: ppm
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.4rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 800
  min_val:
    card:
      type: custom:button-card
      name: "400"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.0rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  max_val:
    card:
      type: custom:button-card
      name: "2000"
      styles:
        card:
          - width: auto
          - padding: 0
          - border: none
          - border-radius: 0
          - background: none
        name:
          - font-size: 1.0rem
          - align-self: start
          - justify-self: start
          - color: rgba(167,176,205,1.0)
          - font-weight: 400
  bar:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - height: 8px
          - width: 330px
          - border-radius: 999px
          - border: 0
          - padding: 0px
          - background: >-
              linear-gradient(to right, rgba(0,255,24,1.0) 0%,
              rgba(152,255,0,1.0) 40%, rgba(255,252,0,1.0) 55%,
              rgba(255,174,0,1.0) 75%, rgba(255,0,0,1.0) 100%)
  cursor:
    card:
      type: custom:button-card
      show_name: false
      show_icon: false
      show_state: false
      styles:
        card:
          - width: 14px
          - height: 32px
          - border-radius: 999px
          - border: 4px solid rgba(42,45,54,1.0)
          - background-color: |
              [[[
                const ppm = Number(entity.state) || 0;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0,   255, 24]  },
                  { p: 40,  c: [152, 255, 0]   },
                  { p: 55,  c: [255, 252, 0]   },
                  { p: 75,  c: [255, 174, 0]   },
                  { p: 100, c: [255, 0,   0]   }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},1.0)`;
              ]]]
  comment:
    card:
      type: custom:button-card
      show_name: true
      show_icon: false
      show_state: false
      name: |
        [[[
          const ppm = Number(entity.state) || 0;
          if (ppm < 900) {
            return "Excellent";
          }
          if (ppm >= 900 && ppm <= 1150) {
            return "Bon";
          }
          if (ppm >= 1151 && ppm <= 1400) {
            return "Acceptable";
          }
          if (ppm >= 1401 && ppm <= 1600) {
            return "Mauvais";
          }
          if (ppm > 1600) {
            return "Malsain";
          }
        ]]]
      styles:
        card:
          - height: 12px
          - width: auto
          - height: 36px
          - border-radius: 999px
          - border: 0
          - padding: 10px
          - background: white
          - background-color: |
              [[[
                const ppm = Number(entity.state) || 0;
                const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
                const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
                const stops = [
                  { p: 0,   c: [0,   255, 24]  },
                  { p: 40,  c: [152, 255, 0]   },
                  { p: 55,  c: [255, 252, 0]   },
                  { p: 75,  c: [255, 174, 0]   },
                  { p: 100, c: [255, 0,   0]   }
                ];
                let i = 1;
                while (i < stops.length && percent > stops[i].p) i++;
                const a = stops[i - 1];
                const b = stops[i];
                const t = (percent - a.p) / (b.p - a.p);
                const lerp = (x, y, t) => Math.round(x + (y - x) * t);
                const r = lerp(a.c[0], b.c[0], t);
                const g = lerp(a.c[1], b.c[1], t);
                const bcol = lerp(a.c[2], b.c[2], t);
                return `rgba(${r},${g},${bcol},0.5)`;
              ]]]
        name:
          - font-size: 1.1rem
          - font-weight: 600
          - color: |
              [[[
                const ppm = Number(entity.state) || 0;
                if (ppm < 900) {
                  return "rgba(0,255,24,1.0)";
                }
                if (ppm >= 900 && ppm <= 1150) {
                  return "rgba(152,255,0,1.0)";
                }
                if (ppm >= 1151 && ppm <= 1400) {
                  return "rgba(255,252,0,1.0)";
                }
                if (ppm >= 1401 && ppm <= 1600) {
                  return "rgba(255,174,0,1.0)";
                }
                if (ppm > 1600) {
                  return "rgba(255,113,0,1.0)";
                }
              ]]]
styles:
  card:
    - background-color: rgba(42,45,54,1.0)
    - aspect-ratio: 2/1
    - cursor: default
  custom_fields:
    icon:
      - position: absolute
      - top: 3%
      - left: 1%
    name:
      - position: absolute
      - top: 3%
      - left: 8%
    separation:
      - position: absolute
      - top: 17%
      - left: 0%
    value:
      - position: absolute
      - top: 30%
      - right: 50%
      - margin-right: 1%
      - transform: translateY(-50%)
    unit:
      - position: absolute
      - left: 50%
      - top: 27%
      - margin-left: 1%
      - transform: translateY(-50%)
    min_val:
      - position: absolute
      - top: 53%
      - left: 2%
    max_val:
      - position: absolute
      - top: 53%
      - right: 2%
    comment:
      - position: absolute
      - left: 50%
      - top: 65%
      - transform: translate(-50%, -50%)
    bar:
      - position: absolute
      - left: 50%
      - top: 45%
      - transform: translate(-50%, -50%)
    cursor:
      - position: absolute
      - top: "[[[ return 'calc(45% - 16px)'; ]]]"
      - left: |
          [[[
            const ppm = Number(entity.state) || 0;
            const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
            const percent = clamp(((ppm - 400) / 1600) * 100, 0, 100);
            const barWidth = 330;
            const halfCursor = 8;
            const offsetPx = (barWidth * percent) / 100;
            return `calc(50% - ${barWidth/2}px + ${offsetPx}px - ${halfCursor}px)`;
          ]]]

modifie l’aspect-ratio dans les styles de la carte support - aspect-ratio: 2.5/1 ou aspect-ratio: 3/1 ou n’importe quelle valeur entre les deux jusqu’à ce que la hauteur te convienne

1 « J'aime »

Ah oui, mince du coup ça écrase tout, je pensais qu’on définissait la hauteur en pixels, pas grave je vais réajuster mes autres positions

Oui, il faut réajuster tes éléments en fonction de la hauteur de la carte support car si tu réduis trop celle-ci il y a de fortes chances que des éléments se superposent

1 « J'aime »