So it may be right - I couldn’t resist a challenge.
So going back to this - and yet it’s a hack and could be improved but here it is (I think some have found out this trick before me):
if you want to build your own HTML hierarchy…: well it turns out you can use the f7-row component because it offers the ability to choose your own HTML tag along with their children.
So if you inspect (“steal the code of…?”) Home Assistant’s page you’ll note that the widget’s animated “pipes” is a rather simple SVG:
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
<path id="return" class="return" vector-effect="non-scaling-stroke" d="M47,0 v15 c0,40 -10,35 -30,35 h-20"></path>
<path id="solar" class="solar" vector-effect="non-scaling-stroke" d="M53,0 v15 c0,40 10,35 30,35 h20"></path>
<path class="grid" id="grid" vector-effect="non-scaling-stroke" d="M0,56 H100"></path>
<circle r="1" class="return" vector-effect="non-scaling-stroke">
<animateMotion repeatCount="indefinite" calcMode="linear" dur="5.26366433175909s">
<mpath xlink:href="#return"></mpath>
</animateMotion>
</circle>
<circle r="1" class="solar" vector-effect="non-scaling-stroke">
<animateMotion repeatCount="indefinite" calcMode="linear" dur="3.511455128333689s">
<mpath xlink:href="#solar"></mpath>
</animateMotion>
</circle>
<circle r="1" class="grid" vector-effect="non-scaling-stroke">
<animateMotion repeatCount="indefinite" calcMode="linear" dur="4.102157928533736s">
<mpath xlink:href="#grid"></mpath>
</animateMotion>
</circle>
</svg>
So how would you translate this into openHAB’s widget definition YAML? - well, like this:
- component: f7-row
config:
tag: svg
xmlns: http://www.w3.org/2000/svg
viewBox: 0 0 100 100
preserveAspectRatio: xMidYMid slice
style:
height: auto
slots:
default:
- component: f7-row
config:
tag: path
id: path1
d: M53,0 v15 c0,40 10,35 30,35 h20
stroke: orange
stroke-width: 1
vector-effect: non-scaling-stroke
fill: none
- component: f7-row
config:
tag: circle
r: 1
vector-effect: non-scaling-stroke
fill: orange
style:
stroke-width: 4
slots:
default:
- component: f7-row
config:
tag: animateMotion
repeatCount: indefinite
calcMode: linear
dur: 5s
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path1"
- component: f7-row
config:
tag: path
id: path2
d: M47,0 v15 c0,40 -10,35 -30,35 h-20
stroke: purple
stroke-width: 1
vector-effect: non-scaling-stroke
fill: none
- component: f7-row
config:
tag: circle
r: 1
vectorEffect: non-scaling-stroke
strokeWidth: 10
fill: purple
slots:
default:
- component: f7-row
config:
tag: animateMotion
repeatCount: indefinite
calcMode: linear
dur: 3s
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path2"
- component: f7-row
config:
tag: path
id: path3
d: M0,56 H100
stroke: teal
stroke-width: 1
vector-effect: non-scaling-stroke
fill: none
- component: f7-row
config:
tag: circle
r: 1
vectorEffect: non-scaling-stroke
strokeWidth: 10
fill: teal
slots:
default:
- component: f7-row
config:
tag: animateMotion
repeatCount: indefinite
calcMode: linear
dur: 3s
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path3"
You can change the speed of the animations (dur
properties) with expressions as appropriate.
There could be built-in improvements in this area in the future since it definititely has potential!
Final widget:
uid: energy_summary
tags: []
props:
parameters: []
parameterGroups: []
timestamp: Jan 7, 2022, 12:59:10 PM
component: f7-card
config:
title: Energy Summary (test)
slots:
content:
- component: f7-block
config:
style:
margin: 0
padding: 0
slots:
default:
- component: f7-block
config:
style:
margin: 0
padding: 0
display: flex
justify-content: space-between
--f7-theme-color: var(--f7-text-color)
--f7-block-font-size: 12px
slots:
default:
- component: f7-col
config:
style:
display: flex
flex-direction: column
align-items: center
slots:
default:
- component: Label
config:
text: Non-fossil
- component: f7-block
config:
style:
height: 80px
width: 80px
border: 2px solid darkgreen
border-radius: 40px
display: flex
justify-content: center
align-items: center
flex-direction: column
slots:
default:
- component: oh-icon
config:
icon: if:mdi:leaf
height: 20px
color: darkgreen
- component: Label
config:
text: 0.7 kWh
style:
font-size: 12px
- component: f7-block
config:
style:
height: 30px
width: 2px
padding: 0
margin: 0
border: 1px solid darkgreen
display: flex
justify-content: center
align-items: center
flex-direction: column
- component: f7-block
config:
style:
margin-top: 0
height: 80px
width: 80px
border: 2px solid teal
border-radius: 40px
display: flex
justify-content: center
align-items: center
flex-direction: column
slots:
default:
- component: oh-icon
config:
icon: if:mdi:transmission-tower
height: 20px
color: teal
- component: oh-link
config:
text: 2.3 kWh
iconF7: arrow_left
iconSize: 12px
iconColor: purple
style:
font-size: 12px
white-space: nowrap
- component: oh-link
config:
text: 5.7 kWh
iconF7: arrow_right
iconSize: 12px
iconColor: blue
style:
font-size: 12px
white-space: nowrap
- component: Label
config:
text: Grid
- component: f7-col
config:
style:
flex-grow: 1
display: flex
flex-direction: column
align-items: center
slots:
default:
- component: Label
config:
text: Solar
- component: f7-block
config:
style:
height: 80px
width: 80px
border: 2px solid orange
border-radius: 40px
display: flex
justify-content: center
align-items: center
flex-direction: column
slots:
default:
- component: oh-icon
config:
icon: if:mdi:solar-power
height: 20px
color: orange
- component: Label
config:
text: 9.5 kWh
style:
font-size: 12px
- component: f7-block
config:
style:
margin: 0
padding: 0
width: 100%
display: flex
height: 125px
justify-content: center
slots:
default:
- component: f7-row
config:
tag: svg
xmlns: http://www.w3.org/2000/svg
viewBox: 0 0 100 100
preserveAspectRatio: xMidYMid slice
style:
height: auto
slots:
default:
- component: f7-row
config:
tag: path
id: path1
d: M53,0 v15 c0,40 10,35 30,35 h20
stroke: orange
stroke-width: 1
vector-effect: non-scaling-stroke
fill: none
- component: f7-row
config:
tag: circle
r: 1
vector-effect: non-scaling-stroke
fill: orange
style:
stroke-width: 4
slots:
default:
- component: f7-row
config:
tag: animateMotion
repeatCount: indefinite
calcMode: linear
dur: 5s
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path1"
- component: f7-row
config:
tag: path
id: path2
d: M47,0 v15 c0,40 -10,35 -30,35 h-20
stroke: purple
stroke-width: 1
vector-effect: non-scaling-stroke
fill: none
- component: f7-row
config:
tag: circle
r: 1
vectorEffect: non-scaling-stroke
strokeWidth: 10
fill: purple
slots:
default:
- component: f7-row
config:
tag: animateMotion
repeatCount: indefinite
calcMode: linear
dur: 3s
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path2"
- component: f7-row
config:
tag: path
id: path3
d: M0,56 H100
stroke: teal
stroke-width: 1
vector-effect: non-scaling-stroke
fill: none
- component: f7-row
config:
tag: circle
r: 1
vectorEffect: non-scaling-stroke
strokeWidth: 10
fill: teal
slots:
default:
- component: f7-row
config:
tag: animateMotion
repeatCount: indefinite
calcMode: linear
dur: 3s
slots:
default:
- component: f7-row
config:
tag: mpath
xlink:href: "#path3"
- component: f7-col
config:
style:
display: flex
flex-direction: column
align-items: center
slots:
default:
- component: Label
config:
text: Gas
- component: f7-block
config:
style:
height: 80px
width: 80px
border: 2px solid darkred
border-radius: 40px
display: flex
justify-content: center
align-items: center
flex-direction: column
slots:
default:
- component: oh-icon
config:
icon: if:mdi:gas
height: 20px
color: darkred
- component: Label
config:
text: 1.7 m³
style:
font-size: 12px
- component: f7-block
config:
style:
height: 30px
width: 2px
padding: 0
margin: 0
border: 1px solid darkred
display: flex
justify-content: center
align-items: center
flex-direction: column
- component: f7-block
config:
style:
margin-top: 0
height: 80px
width: 80px
border: 2px solid gray
border-radius: 40px
display: flex
justify-content: center
align-items: center
flex-direction: column
slots:
default:
- component: oh-icon
config:
icon: if:mdi:home
height: 20px
color: gray
- component: Label
config:
text: 12.9 kWh
style:
font-size: 12px
white-space: nowrap
- component: Label
config:
text: Home