Example

title: Home
config:
  image: /local/floorplan/examples/home/home.svg
  stylesheet: /local/floorplan/examples/home/home.css
  log_level: info
  console_log_level: info

  defaults:
    hover_action: hover-info
    tap_action: more-info

  rules:
    - entity: light.garage
      element: light.garage
      state_action:
        - action: call-service
          service: floorplan.image_set
          service_data:
            image: /local/floorplan/examples/home/light_${entity.state}.svg
            cache: true
      tap_action: toggle

    - entity: light.main_bedroom
      element: light.main_bedroom
      state_action:
        - action: call-service
          service: floorplan.image_set
          service_data:
            image: /local/floorplan/examples/home/light_on.svg
            cache: true
        - service: floorplan.class_set
          service_data: light-${entity.state}
      tap_action: toggle

    - entity: '*'
      element: light.garage.last_changed
      state_action:
        - action: call-service
          service: floorplan.text_set
          service_data:
            text: '${util.date.timeago(new Date(entities["light.garage"].last_changed))}'

    - entity: light.garage
      element: light.garage.button
      state_action:
        action: call-service
        service: floorplan.class_set
        service_data: 'button-${entity.state}'
      tap_action:
        action: call-service
        service: homeassistant.toggle

    - entity: light.garage
      element: light.garage.text
      state_action:
        action: call-service
        service: floorplan.text_set
        service_data: '${entity.state.toUpperCase()}'
      tap_action: false

    - entity: light.main_bedroom
      element: light.main_bedroom.button
      state_action:
        action: call-service
        service: floorplan.class_set
        service_data: 'button-${entity.state}'
      tap_action: homeassistant.toggle

    - entity: light.main_bedroom
      element: light.main_bedroom.text
      state_action:
        action: call-service
        service: floorplan.text_set
        service_data: '${entity.state.toUpperCase()}'
      tap_action: false

    - entity: switch.living_area_fan
      tap_action: false
      state_action:
        action: call-service
        service: floorplan.class_set
        service_data:
          class: '${(entity.state === "on") ? "spinning" : ""}'

    - entity: switch.living_area_fan
      element: switch.living_area_fan.button
      state_action:
        action: call-service
        service: floorplan.class_set
        service_data: button-${entity.state}
      hold_action:
        action: call-service
        service: homeassistant.toggle
        service_data:
          entity_id: switch.living_area_fan

    - entity: switch.living_area_fan
      element: switch.living_area_fan.text
      state_action:
        action: call-service
        service: floorplan.text_set
        service_data: '${entity.state.toUpperCase()}'
      tap_action: false

    - entity: camera.zagreb
      state_action:
        - action: call-service
          service: floorplan.image_set
          service_data:
            image: '${entity.attributes.entity_picture}'
            image_refresh_interval: 10
        - service: floorplan.class_set
          service_data:
            class: weathericon

    - entities:
        - binary_sensor.main_bedroom
        - binary_sensor.living_area
      state_action:
        action: call-service
        service: floorplan.style_set
        service_data:
          style: |
            fill: ${ entity.state === "on" ? "#F9D27C" : "#7CB1F9" };
            transition: ${ entity.state === "off" ? "fill 5s ease" : "" };

    - entity: sensor.moisture_level
      state_action:
        action: call-service
        service: floorplan.style_set
        service_data:
          element: moisture-level-clip-path
          style: |
            >
            var height = Math.ceil(elements['sensor.moisture_level'].getBBox().height);
            return `transform: translate(0, ${height - Math.floor(entity.attributes.level / (100 / height))}px)`;

    - entity: sensor.wind_direction
      state_action:
        action: call-service
        service: floorplan.style_set
        service_data:
          style: |
            >
            var rotation = Math.floor(entity.state) - 90;

            return `
              transform-box: fill-box;
              transform-origin: center;
              transform: rotate(${rotation}deg);
            `;

    - entity: sensor.test
      element: triangle
      state_action:
        action: call-service
        service: floorplan.style_set
        service_data:
          style: |
            >
            var rotation = ((Math.floor(entity.attributes.level) * 1.8) - 90);

            return `
              transform-box: fill-box;
              transform-origin: center bottom;
              transform: rotate(${rotation}deg);
            `;
/* SVG size */

#floorplan {
  padding: 10px;
}

#floorplan>svg {
  max-width: 700px;
}

/* SVG elements */

svg * {
  vector-effect: non-scaling-stroke !important;
}

/* Hover over */

.floorplan-shape:hover,
g.floorplan-hover> :not(text):hover,
g.floorplan-click> :not(text):hover,
g.floorplan-long-click> :not(text):hover,
:not(text).floorplan-hover:hover,
:not(text).floorplan-click:hover,
:not(text).floorplan-long-click:hover {
  stroke: #03a9f4 !important;
  stroke-width: 1px !important;
  stroke-opacity: 1 !important;
}

/* Animation */

.spinning {
  animation-name: spin;
  animation-duration: 5s;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
  transform-origin: 50% 50%;
  transform-box: fill-box;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

/* Binary sensors */

.binary-sensor-on {
  fill: #f9d27c !important;
}

.binary-sensor-off {
  fill: #7cb1f9 !important;
  transition: fill 5s ease;
}

/* Buttons */

.button-on rect {
  fill: #1aba92 !important;
}

.button-off rect {
  fill: #d32f2f !important;
}

.button-on tspan,
.button-off tspan {
  fill: white !important;
}

/* Lights */

.light-on * {
  /* Nothing to do */
}

.light-off * {
  -webkit-filter: grayscale(100%);
  filter: grayscale(100%);
  filter: gray;
}

Assets

All assets can be found in the ha-floorplan repository on GitHub.

Here you’ll find the .svg, .css and .yaml used in the example.

Updated: