Cards Machine a laver

Je vais te mettre le code commenté de façon à ce que tu comprennes le fonctionnement.
Tout d’abord, c’est fait à partir de custom:button-card : GitHub - custom-cards/button-card: ❇️ Lovelace button-card for home assistant

Il faudra donc installer cette carte depuis HACS ou manuellement (tu as la procédure d’installation décrite dans le lien ci-dessus ainsi que la documentation de la carte).

Je vais éditer plusieures fois ce message pour tout expliquer, donc soit patient.

Les images utilisées (à mettre dans le répertoire : « www/images » par File Editor par exemple) :

(je ne sais pas comment insérer une image .png de façon à conserver la transparence, il faudra donc éditer les images avec un logiciel de retouche de façon à remplacer le blanc par de la transparence…)

Nous allons commencer par le fond, c’est à dire la carte avec l’image du lave-linge. Il faudra donc ajouter une nouvelle carte « custom:button-card » sur un tableau de bord quelconque.

(je pars du principe que ces notions sont acquises).

Le code :

type: custom:button-card
styles:
  card:
    - background-image: url(/local/images/lave-linge.png)
    - width: 480px
    - height: 480px
    - background-size: cover
    - background-position: center
    - border-radius: 0px
    - border: none
    - background-color: rgba(250,250,250,1.0)

Nous ajoutons donc la carte (« type: custom:button-card ») puis nous allons définir les attributs de celle-ci :

- background-image: url((/local/images/lave-linge.png) : nous indiquons le chemin d’accès à l’image de fond (/local correspond au répertoire www)

- width et - height : nous déterminons la taille de la carte en pixels.

- background-size: cover : j’indique que l’image doit couvrir l’ensemble de la carte

- background-position: center : j’indique que le fond part du centre de la carte

- border-radius: 0px et - border: none : j’indique de ne pas arrondir les coins de la carte et de ne pas mettre de bordure autour

- background-color: rgba(250,250,250,1.0) : j’indique la couleur de fond de la carte (cette couleur sera visible car le fond de l’image utilisée est transparente) - rgb sont les composantes Rouge (Red), Verte (Green) et Bleue (Blue) de la couleur de fond (de 0 à 255 pour chacune des composantes) et a représente la composante Alpha, c’est à dire la transparence (de 0 à 1 avec un pas de 0,1 - 0 correspondant à une transparence totale et 1.0 une opacité totale).

Pour montrer le fonctionnement, j’ai créé une entrée de type « Interrupteur » que j’utilise pour afficher l’image du tambour plein et lancer la rotation (l’entrée s’appelle input_boolean.lave_linge)

Pour le tambour plein, nous allons utiliser un « custom_fields », c’est à dire un champ personnalisé permettant d’afficher n’importe quelle carte sur la carte « support » que nous venons de créer. Pour cela, nous allons appeler et définir ce « custom_fields ». L’appel se fait simplement en ajoutant custom_fields: au code de la carte support puis en lui attribuant un nom (ici je l’ai appelé « tambour »). Puis nous allons définir ce que doit afficher ce custom_fields, ici, une autre carte custom:button-card. Nous allons donc ajouter (en respectant l’indentation de deux espaces pour chaque niveau) card: puis type: custom:button-card

Nous allons pouvoir déterminer les attributs de cette nouvelle custom:button-card avec la propriété styles: de la même manière que nous avons déterminé les styles de la carte support.

Le code avec le custom_fields nouvellement créé :

type: custom:button-card
custom_fields:
  tambour:
    card:
      type: custom:button-card
      entity: input_boolean.lave_linge
      show_icon: false
      show_name: false
      styles:
        card:
          - width: 160px
          - height: 160px
          - border-radius: 50%
          - background-image: none
          - background-size: cover
          - background-position: center
          - background-color: rgba(28,28,28,0.2)
styles:
  card:
    - background-image: url(/local/images/lave-linge.png)
    - width: 480px
    - height: 480px
    - background-size: cover
    - background-position: center
    - border-radius: 0px
    - border: none
    - background-color: rgba(250,250,250,1.0)

Ce custom_fields créé va apparaitre en bas à droite de la carte support. Il va donc falloir le positionner au bon endroit. Pour le faire, nous allons définir sa position en ajoutant aux styles de la carte support les attributs permettant de mettre le custom_fields à sa place :

type: custom:button-card
custom_fields:
  tambour:
    card:
      type: custom:button-card
      entity: input_boolean.lave_linge
      show_icon: false
      show_name: false
      styles:
        card:
          - width: 160px
          - height: 160px
          - border-radius: 50%
          - background-image: none
          - background-size: cover
          - background-position: center
          - background-color: rgba(28,28,28,0.2)
styles:
  card:
    - background-image: url(/local/images/lave-linge.png)
    - width: 480px
    - height: 480px
    - background-size: cover
    - background-position: center
    - border-radius: 0px
    - border: none
    - background-color: rgba(250,250,250,1.0)
  custom_fields:
    tambour:
      - position: absolute
      - top: 140px
      - left: 103px

J’ai donc ajouté aux styles de la carte support des attributs pour le custom_fields « tambour ».

Le premier attribut - position: absolute indique que la position du custom_fields sera fixée. - top: et -left: permettent de donner la position du coin supérieur gauche du custom_fields.

J’ai ajouté à la carte une proprieté entity qui va la lier à mon entrée de type « Interrupteur » de façon à ce que le passage de l’entrée de « on » à « off » et inversement, sera automatiquement pris en compte dans la propriété state (état) du custom_fields.

Avec show_icon: false et show_name: false, j’indique de ne pas afficher l’icône et le nom de l’entité input_boolean.lave_linge.

Nous allons ensuite déterminer les attributs variables en fonction de l’état de l’entité (« on » ou « off ») et donc afficher une image de tambour plain quand l’état de l’entité est sur « on ».

Le code à ce stade :

type: custom:button-card
custom_fields:
  tambour:
    card:
      type: custom:button-card
      entity: input_boolean.lave_linge
      show_icon: false
      show_name: false
      styles:
        card:
          - width: 160px
          - height: 160px
          - border-radius: 50%
          - background-image: none
          - background-size: cover
          - background-position: center
          - background-color: rgba(28,28,28,0.2)
      state:
        - value: "on"
          styles:
            card:
              - background-image: url(/local/images/tambour-plein.png)
styles:
  card:
    - background-image: url(/local/images/lave-linge.png)
    - width: 480px
    - height: 480px
    - background-size: cover
    - background-position: center
    - border-radius: 0px
    - border: none
    - background-color: rgba(250,250,250,1.0)
  custom_fields:
    tambour:
      - position: absolute
      - top: 140px
      - left: 103px

J’ai donc ajouté les lignes suivantes pour dire que quand l’état (state) de l’entité est égal à « on », j’affiche l’image du tambour plein :

      state:
        - value: "on"
          styles:
            card:
              - background-image: url(/local/images/tambour-plein.png)

Quand l’état n’est pas « on », on revient sur l’attribut - background-image: none

Nous allons voir maintenant les lignes permettant la rotation du tambour plein :

Pour définir l’animation, nous allons ajouter cette ligne dans les styles du custom_fields quand l’état de l’entité est sur « on » : - animation: rotate 2s linear infinite

rotate : nous voulons une animation de type rotation ;

2s : la rotation se fera en 2 secondes (plus la durée de roation est petite, plus le custom_fields tournera vite et inversement) ;

linear : la rotation sera linéaire ;

infinite : la rotation se fera de manière permanente.

Nous allons devoir ensuite spécifier que le custom_fields doit tourner sur lui-même dans le sens des aiguilles d’une montre. Nous allons ajouter donc ces lignes sous la ligne de l’attribut animation :

      extra_styles: |
        @keyframes rotate {
          0% { transform: rotate(0deg); }
          100% { transform: rotate(360deg); }
        }

Attention à bien respecter les indentations : 2 espaces par niveau.

Le code avec la rotation quand l’entité input_boolean.lave_linge est sur « on » :

type: custom:button-card
custom_fields:
  tambour:
    card:
      type: custom:button-card
      entity: input_boolean.lave_linge
      show_icon: false
      show_name: false
      styles:
        card:
          - width: 160px
          - height: 160px
          - border-radius: 50%
          - background-image: none
          - background-size: cover
          - background-position: center
          - background-color: rgba(28,28,28,0.2)
      state:
        - value: "on"
          styles:
            card:
              - background-image: url(/local/images/tambour-plein.png)
              - animation: rotate 2s linear infinite
      extra_styles: |
        @keyframes rotate {
          0% { transform: rotate(0deg); }
          100% { transform: rotate(360deg); }
        }
styles:
  card:
    - background-image: url(/local/images/lave-linge.png)
    - width: 480px
    - height: 480px
    - background-size: cover
    - background-position: center
    - border-radius: 0px
    - border: none
    - background-color: rgba(250,250,250,1.0)
  custom_fields:
    tambour:
      - position: absolute
      - top: 140px
      - left: 103px

Pour le bouton, il s’agit là encore d’ajouter un custom_fields et de le positionner à l’endroit voulu :

type: custom:button-card
custom_fields:
  tambour:
    card:
      type: custom:button-card
      entity: input_boolean.lave_linge
      show_icon: false
      show_name: false
      styles:
        card:
          - width: 160px
          - height: 160px
          - border-radius: 50%
          - background-image: none
          - background-size: cover
          - background-position: center
          - background-color: rgba(28,28,28,0.2)
      state:
        - value: "on"
          styles:
            card:
              - background-image: url(/local/images/tambour-plein.png)
              - animation: rotate 2s linear infinite
      extra_styles: |
        @keyframes rotate {
          0% { transform: rotate(0deg); }
          100% { transform: rotate(360deg); }
        }
  bouton_marche_arret:
    card:
      type: custom:button-card
      icon: mdi:power
      entity: input_boolean.lave_linge
styles:
  card:
    - background-image: url(/local/images/lave-linge.png)
    - width: 480px
    - height: 480px
    - background-size: cover
    - background-position: center
    - border-radius: 0px
    - border: none
    - background-color: rgba(250,250,250,1.0)
  custom_fields:
    tambour:
      - position: absolute
      - top: 140px
      - left: 103px
    bouton_marche_arret:
      - position: absolute
      - top: 25px
      - left: 370px

La différence avec le custom_fields du tambour est l’ajout de l’icône (icon: mdi:power). Je définis l’entité du custom_fields avec mon entrée input_boolean.lave-linge de façon à pouvoir gérer directement l’action lors du clic sur le bouton et les modifications graphiques en fonction de l’état de l’entité (« on » ou « off »).

L’entité étant de type Interrupteur, je vais utiliser directement une action « toggle » (basculer) lors du clic, ce qui passera l’entité de « on » à « off » ou inversement à cahque clic.

Pour ce faire, j’ajoute donc le code pour définir l’action sur le clic et en même temps l’absence d’action sur un clic maintenu :

      tap_action:
        action: toggle
      hold_action:
        action: none

Comme d’habitude, il faut veiller à respecter l’indentation, tap_action devant être au même niveau que type: custom:button-card du custom_fields bouton_marche_arret.

Nous allons ensuite définir les attributs de styles de la carte (card) et l’icône (icon) du custom_fields :

      styles:
        card:
          - aspect-ratio: 1/1
          - width: 100%
          - height: 70px
          - border-radius: 50%
          - background: >-
              conic-gradient(rgba(211, 211, 211, 0.8) 100deg, rgba(255, 255,
              255, 1) 130deg, rgba(211, 211, 211, 0.8) 170deg, rgba(211, 211, 211,
              0.8) 190deg)
        icon:
          - width: 70%

Nous utilisons ici un nouvel attribut qui est le rapport entre la largeur et la hauteur de la carte (- aspect-ratio:) que nous définissons à 1/1 : hauteur et largeur identiques. Un aspect-ratio de 2/1 signifie que la carte est deux fois plus large que haute et inversement pour un aspect-ratio de 1/2.

Nous définissons une largeur de 100% et une hauteur de 70 pixels (donc la largeur sera elle aussi de 70 pixels de part l’aspect-ratio) et un border-radius de 50%. Sur une carte ayant un aspect-ratio de 1/1, un border-radius de 50% va générer une carte ronde. Avec un aspect-ratio de 2/1 avec une hauteur de 70 pixels, pour avoir une carte ayant une forme de « gelule », il aurait fallu mettre le border-radius à 35 pixels.

Pour donner un aspect brillant au bouton, nous allons ajouter un dégradé conique au fond du bouton avec le code suivant (je te laisse jouer avec les différentes valeurs d’angle pour voir les possibilités de ce type de dégradé) :

- background: >-
              conic-gradient(rgba(211, 211, 211, 0.8) 100deg, rgba(255, 255,
              255, 1) 130deg, rgba(211, 211, 211, 0.8) 170deg, rgba(211, 211, 211,
              0.8) 190deg)

Nous fixons ensuite un attribut de l’icône : sa largeur avec - width: 70%. C’est donc dans les styles que nous allons pouvoir définir les attributs des éléments constitutifs de custom:button-card (« card », « icon », « name », « label », etc.).

Nous allons finir avec le comportement (aspect graphique) du custom_fields en fonction de l’état de son entité (input_boolean.lave_linge).

Nous allons donc ajouter les lignes suivantes (au même niveau que type: custom:button-card du custom_fields bouton_marche_arret) :

      state:
        - value: "on"
          styles:
            card:
              - box-shadow: 0px 0px 8px 4px rgba(64,192,64,0.8)
              - border: 2px rgba(128,128,128,1.0) outset
            icon:
              - color: green
        - value: "off"
          styles:
            card:
              - box-shadow: 2px 2px 4px 0px rgba(32,32,32,0.5)
              - border: 3px rgba(128,128,128,1.0) outset
            icon:
              - color: black

Dans l’état « off », nous ajoutons tout d’abord un effet d’ombre (box-shadow) avec un décalage à droite et vers le bas de 2 pixels et un flou de 4 pixel (le quatrième paramètre est l’épaisseur de l’ombre autour de la carte) avec une couleur grise avec 50% d’opacité. Nous ajoutons ensuite une bordure extérieure (outset) de 3 pixels d’épaisseur ayant une couleur grise moyenne avec une opacité de 100% (rgba(128,128,128,1.0)). C’est la mention outset qui va donner un effet 3D au bouton. Nous définissons la couleur de l’icône (- color: black, couleur que nous aurions pu écrire rgb(0,0,0) ou rgba(0,0,0,1.0) ou #000000 qui est le code HTML pour le noir)

Pour l’état « on », nous changeons la couleur de l’icône que nous passons au vert (green), nous modifions l’ombrage de façon à obtenir un halo vert autour du bouton en supprimant le décalage vers la droite et le bas, en modifiant le flou à 8 pixels et en définissant une étendue de 4 pixels et en appliquant une nuance de vert ayant une opacité de 80% (- box-shadow: 0px 0px 8px 4px rgba(64,192,64,0.8)). Nous modifions enuite l’épaisseur de la bordure du bouton d’un pixel pour donner un léger effet enfoncé par rapport à l’état « off ».

Le code complet :

type: custom:button-card
custom_fields:
  tambour:
    card:
      type: custom:button-card
      entity: input_boolean.lave_linge
      show_icon: false
      show_name: false
      styles:
        card:
          - width: 160px
          - height: 160px
          - border-radius: 50%
          - background-image: none
          - background-size: cover
          - background-position: center
          - background-color: rgba(28,28,28,0.2)
      state:
        - value: "on"
          styles:
            card:
              - background-image: url(/local/images/tambour-plein.png)
              - animation: rotate 2s linear infinite
      extra_styles: |
        @keyframes rotate {
          0% { transform: rotate(0deg); }
          100% { transform: rotate(360deg); }
        }
  bouton_marche_arret:
    card:
      type: custom:button-card
      name: Power
      icon: mdi:power
      entity: input_boolean.lave_linge
      show_name: false
      state:
        - value: "on"
          styles:
            card:
              - box-shadow: 0px 0px 8px 4px rgba(64,192,64,0.8)
              - border: 2px rgba(128,128,128,1.0) outset
            icon:
              - color: green
        - value: "off"
          styles:
            card:
              - box-shadow: 2px 2px 4px 0px rgba(32,32,32,0.5)
              - border: 3px rgba(128,128,128,1.0) outset
            icon:
              - color: black
      styles:
        card:
          - aspect-ratio: 1/1
          - width: 100%
          - height: 70px
          - border-radius: 50%
          - background: >-
              conic-gradient(rgba(211, 211, 211, 0.8) 100deg, rgba(255, 255,
              255, 1) 130deg, rgba(211, 211, 211, 0.8) 170deg, rgba(211, 211, 211,
              0.8) 190deg)
        icon:
          - width: 70%
      tap_action:
        action: toggle
      hold_action:
        action: none
styles:
  card:
    - background-image: url(/local/images/lave-linge.png)
    - width: 480px
    - height: 480px
    - background-size: cover
    - background-position: center
    - border-radius: 0px
    - border: none
    - background-color: rgba(250,250,250,1.0)
  custom_fields:
    tambour:
      - position: absolute
      - top: 140px
      - left: 103px
    bouton_marche_arret:
      - position: absolute
      - top: 25px
      - left: 370px

Voilà, c’est fini :wink: N’hésites pas si tu as des questions où si des points te paraissent pas très clairs.

12 « J'aime »