Lovelace Icon Animation Help

Hello HA Community! Having an issue getting a custom SVG animation to run in HA, and need some assistance.

I created the following custom rain drop animation that I want to display when a script is running that controls my automatic watering system:

<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
  <defs>
    <radialGradient id="rg" r="1" fx="0.25" fy="0.5">
      <stop offset="0%" stop-color="white"></stop>
      <stop offset="75%" stop-color="#1B7FE4"></stop>
    </radialGradient>
  </defs>
  
  <!-- Group for droplet animation with transformation -->
  <g transform="translate(50, 0) rotate(90, 50, 50)">
    <!-- Teardrop shape -->
    <path fill="url(#rg)" d="M 50,10
             c -40,50 -20,50 0,80
             c 40,-40 20,-50 0,-80" />

    <!-- Falling drop animation -->
    <animateTransform attributeName="transform" type="translate" dur="2s" repeatCount="indefinite" values="0,0;0,60" keyTimes="0;1"/>
  </g>
</svg>

I have dropped this “droplet_animation.svg” into my homeassistant/www directory and then to test if it works, just referencing it in a picture elements card:

type: picture-elements
image: /config/www/droplet_animation.SVG
elements:
  - type: image
    image: /config/www/droplet_animation.SVG
    style:
      left: 50%
      top: 50%
      width: 100px
      height: 100px
      transform: translate(-50%, -50%)

but I the card just shows up like this:
image

It looks like HA at least likes the syntax from looking at it in my Studio Code Server running in HA:

And my config.yaml lovelace resources:

lovelace:
  resources:
    - url: /hacsfiles/aarlo-glance/aarlo-glance.js
      type: module
    - url: /hacsfiles/lovelace-card-mod/card-mod.js
      type: module
    - url: /hacsfiles/button-card/button-card.js
      type: module
    - url: /local/droplet_animation.svg   # Custom raindrop animation made for sprinkler system
      

But for some reason it’s not working. I have also tried creating a resource in my lovelace config, referencing the local filepath as the directory as well with no luck. I have confirmed that the animation works when I just open the svg file on my Windows PC, but it doesn’t work in here. Any suggestions?

try

image: /local/droplet_animation.SVG
1 Like

That was it! Omg I was so close haha. Weird thing though, as soon as I put the appropriate code in, it broke another card that was working (my ultimate goal on this card) which referenced the same element. Now I’m getting "custom element doesn’t exist: button-card.

type: custom:button-card
entity: script.1718301656716
name: Start Watering Sequence
show_state: true
tap_action:
  action: call-service
  service: script.turn_on
  service_data:
    entity_id: script.1718301656716
styles:
  card:
    - width: 200px
    - height: 100px
    - background: |
        [[[
          return entity.state === 'on' ? 'lightgreen' : 'white';
        ]]]
  name:
    - font-size: 14px
  icon:
    - color: |
        [[[
          return entity.state === 'on' ? 'cyan' : 'gray';
        ]]]
    - width: 40px
    - height: 40px
  state:
    - font-size: 12px
  grid:
    - position: relative
    - align-items: center
    - justify-items: center
    - template: |
        [[[ 
          if (entity.state === 'on') {
            return `
              <img src="/local/droplet_animation.svg" style="width: 40px; height: 40px;">
            `;
          } else {
            return `
              <ha-icon icon="mdi:water"></ha-icon>
            `;
          }
        ]]]

Any ideas on why that would happen, or what I need to do to fix it and correctly reference this animation? Trying to display this when watering, and just a plain old gray water icon when the script isn’t running. Thanks

Re-download or re-install Custom Button-Card via HACs if this is the message you are seeing.

image

It will not affect your Lovelace code.

1 Like

Thanks, that worked too. I know in this code I already had an icon that changes color based on state, but I want the on state to change from the lightgreen background and cyan icon to the svg animation with the lightgreen background. Tried this but it only displays the color changes with no icon at all, and some text in the background that says [object Object][object Object]:

type: custom:button-card
entity: script.test_script
name: Start Watering Sequence
show_state: true
tap_action:
  action: call-service
  service: script.turn_on
  service_data:
    entity_id: script.test_script
styles:
  card:
    - width: 200px
    - height: 100px
    - background-color: |
        [[[
          return entity.state === 'on' ? 'lightgreen' : 'white';
        ]]]
  name:
    - font-size: 14px
  icon:
    - display: none
  state:
    - font-size: 12px
  grid:
    - position: relative
    - align-items: center
    - justify-items: center
custom_fields:
  svg_icon:
    - position: absolute
    - top: 50%
    - left: 50%
    - transform: translate(-50%, -50%)
    - width: 40px
    - height: 40px
    - content: |
        [[[
          return entity.state === 'on'
            ? '<img src="/local/droplet_animation.svg" style="width: 40px; height: 40px;">'
            : '<ha-icon icon="mdi:water" style="width: 40px; height: 40px;"></ha-icon>';
        ]]]

Any ideas on what I’m missing?

  1. This line is removing the icon
  icon:
    - display: none
  1. You have switched from template: | - content: | from the original code?

The code has significant changes from 1 hour ago

You also have an indent issue with custom_fields

try this

type: custom:button-card
entity: script.test_script
name: Start Watering Sequence
show_state: true
tap_action:
  action: call-service
  service: script.turn_on
  service_data:
    entity_id: script.test_script
styles:
  card:
    - width: 200px
    - height: 100px
    - background-color: |
        [[[
          return entity.state === 'on' ? 'lightgreen' : 'white';
        ]]]
  name:
    - font-size: 14px
  icon:
    - color: |
        [[[
          return entity.state === 'on' ? 'cyan' : 'gray';
        ]]]
    - width: 40px
    - height: 40px
  state:
    - font-size: 12px
  grid:
    - position: relative
    - align-items: center
    - justify-items: center
  custom_fields:
   svg_icon:
    - position: absolute
    - top: 50%
    - left: 50%
    - transform: translate(-50%, -50%)
    - width: 40px
    - height: 40px
    - content: |
        [[[
          return entity.state === 'on'
            ? '<img src="/local/droplet_animation.svg" style="width: 40px; height: 40px;">'
            : '<ha-icon icon="mdi:water" style="width: 40px; height: 40px;"></ha-icon>';
        ]]]

Yea I tried my old code and it didn’t work, so I threw it into ChatGPT just to see if it could figure it out. It changed the code around like you saw, but it also didn’t work. I also didn’t want to trigger the original script because it’s actually doing things I don’t want to keep triggering. So I replaced it with the test_script. Below, I’ll paste the original code I was working on, but replacing it with the test script. It all works except when I turn it on, it won’t display the svg animation. It just displays the cyan icon. What should I do to replace the cyan icon with the svg animation when it runs?

type: custom:button-card
entity: script.test_script
name: Start Watering Sequence
show_state: true
tap_action:
  action: call-service
  service: script.turn_on
  service_data:
    entity_id: script.test_script
styles:
  card:
    - width: 200px
    - height: 100px
    - background: |
        [[[
          return entity.state === 'on' ? 'lightgreen' : 'white';
        ]]]
  name:
    - font-size: 14px
  icon:
    - color: |
        [[[
          return entity.state === 'on' ? 'cyan' : 'gray';
        ]]]
    - width: 40px
    - height: 40px
  state:
    - font-size: 12px
  grid:
    - position: relative
    - align-items: center
    - justify-items: center
    - template: |
        [[[ 
          if (entity.state === 'on') {
            return `
              <img src="/local/droplet_animation.svg" style="width: 40px; height: 40px;">
            `;
          } else {
            return `
              <ha-icon icon="mdi:water"></ha-icon>
            `;
          }
        ]]]

I have a button card that uses an SVG and my code is under entity_picture.

chrome-capture-2024-6-13

Here is a portion of the code

        type: custom:button-card
        entity: fan.bedroom_fan
        icon: mdi:fan
        show_state: false
        show_name: false
        show_entity_picture: true
        entity_picture: |
          [[[
          if (states['sensor.fan_direction_speed'].state == 'forward16') 
          return "/local/animated/forward16.svg";
          else return "/local/pics/tr2.png";
           ]]]
        size: 100%
1 Like

Tried your code from your edited post and it functions the same as the code I just posted.

        type: custom:button-card
        entity: fan.bedroom_fan
        icon: mdi:fan
        show_state: false
        show_name: false
        show_entity_picture: true
        entity_picture: |
          [[[
          if (states['sensor.fan_direction_speed'].state == 'forward16') 
          return "/local/animated/forward16.svg";
          else return "/local/pics/tr2.png";
           ]]]
        size: 100%

I’ll try to adapt my code to work with this. I currently don’t have a still image for the off state like you do. Can I just use a mdi:icon return instead of your path in the “else return” part?

Test this first and we can tackle the the little things once we get your SVG working.

type: custom:button-card
entity: script.test_script
icon: mdi:fan
show_state: false
show_name: false
show_entity_picture: true
entity_picture: |
          [[[
          if (states['script.test_script'].state == 'on') 
          return "/local/droplet_animation.svg";
          else return "/local/droplet_animation.svg";
           ]]]
size: 100%
styles:
  card:
    - width: 200px
    - height: 100px
    - background: |
        [[[
          return entity.state === 'on' ? 'lightgreen' : 'white';
        ]]]

size: 100% controls the size of the SVG so if the SVG is too big adjust the percentage to a lower value.

Tested it at 50% size and it looks like this when I run the script:

image

Never shows the svg.

do you have the SVG inside the WWW folder?

/local/ = www

Yes, check the original post, I took a SS of my config folder through Studio Code Server.

This code works:

image

type: picture-elements
image: /config/www/droplet_animation.SVG
elements:
  - type: image
    image: /local/droplet_animation.SVG
    style:
      left: 50%
      top: 50%
      width: 100px
      height: 100px
      transform: translate(-50%, -50%)

When you double click the animation in the file editor it should open up the file in your browser and the SVG should appear and move. Does that happen?

Nothing happens when I double click on it.

image

But it works on the custom picture elements card

I should have said one click

I tested both. Single or double click does nothing

rename it to all lowercase .SVG needs to be .svg

That worked! And it made your latest code work:

type: custom:button-card
entity: script.test_script
icon: mdi:fan
show_state: false
show_name: false
show_entity_picture: true
entity_picture: |
  [[[
  if (states['script.test_script'].state == 'on') 
  return "/local/droplet_animation.svg";
  else return "/local/droplet_animation.svg";
   ]]]
size: 10%
styles:
  card:
    - width: 200px
    - height: 100px
    - background: |
        [[[
          return entity.state === 'on' ? 'lightgreen' : 'white';
        ]]]

But this still doesn’t work:

type: custom:button-card
entity: script.test_script
name: Start Watering Sequence
show_state: true
tap_action:
  action: call-service
  service: script.turn_on
  service_data:
    entity_id: script.test_script
styles:
  card:
    - width: 200px
    - height: 100px
    - background-color: |
        [[[
          return entity.state === 'on' ? 'lightgreen' : 'white';
        ]]]
  name:
    - font-size: 14px
  icon:
    - color: |
        [[[
          return entity.state === 'on' ? 'cyan' : 'gray';
        ]]]
    - width: 40px
    - height: 40px
  state:
    - font-size: 12px
  grid:
    - position: relative
    - align-items: center
    - justify-items: center
  custom_fields:
    svg_icon:
      - position: absolute
      - top: 50%
      - left: 50%
      - transform: translate(-50%, -50%)
      - width: 40px
      - height: 40px
      - content: |
          [[[
            return entity.state === 'on'
              ? '<img src="/local/droplet_animation.svg" style="width: 40px; height: 40px;">'
              : '<ha-icon icon="mdi:water" style="width: 40px; height: 40px;"></ha-icon>';
          ]]]

Getting closer!!!

I haven’t added an svg in this manner so I’d have to do some testing.

So I understand, what are you trying to achieve with the 2nd code set? Is it only to show the icon when the state is OFF?