OH4: SVG Animation using shape other than circle

Hi All

I am trying to replicate an animation from an APP inside my openHAB. With help so far I have managed to get the following working:

Inverter Animation

The animation uses the following code:

                            - component: f7-row
                              config:
                                preserveAspectRatio: xMidYMid slice
                                style:
                                  height: auto
                                tag: svg
                                viewBox: 0 0 80 140
                                xmlns: http://www.w3.org/2000/svg
                              slots:
                                default:
                                  - component: f7-row
                                    config:
                                      d: M0,10 H25 A 10 10 45 0 1 35 20 V32
                                      fill: none
                                      id: solarInverter
                                      stroke: orange
                                      stroke-width: 2
                                      tag: path
                                      vector-effect: non-scaling-stroke
                                  - component: f7-row
                                    config:
                                      fill: orange
                                      r: 2
                                      style:
                                        stroke-width: 4
                                      tag: circle
                                      vector-effect: non-scaling-stroke
                                    slots:
                                      default:
                                        - component: f7-row
                                          config:
                                            calcMode: linear
                                            dur: 3s
                                            keyPoints: 0;1
                                            keyPointsReverse: 1;0
                                            keyTimes: 0;1
                                            repeatCount: indefinite
                                            tag: animateMotion
                                          slots:
                                            default:
                                              - component: f7-row
                                                config:
                                                  tag: mpath
                                                  xlink:href: "#solarInverter"

I would like to try and get the animated circle to have “arrows” in it, so it looks something like:

circle_with_arrows

My Google Skills are not brining anything up - all the examples I can find use the circle.

I woulod appreciate any hints on how to achieve something like this?

Thanks
Mark

1 Like

You can animate groups as well as individual elements. To group elements together make the elements children of a g element. Then you also just make the animation tag a child of that same group element.

As a side note you’re on a recent enough version of OH that you don’t need to use the tag trick to get this svg tags to work. You can just use the tag name directly in the component line. For example:

- component: f7-row
  config:
    tag: circle

can be made just:

- component: circle

for a much more readable widget.

Sorry Justin, I am not sure I understand what you mean here?

Do you mean?

  - component: g
    config:
    slots:
     default:
      - component: circle
        config:
          fill: red
          r: 2
          strokeWidth: 10
          vectorEffect: non-scaling-stroke
      - component: arrow
        config:
          fill: red
          r: 2
          strokeWidth: 10
          vectorEffect: non-scaling-stroke
        slots:
          default:
            - component: f7-row
              config:
                calcMode: linear
                dur: 3s
                keyPoints: 1;0
                keyPointsReverse: 1;0
                keyTimes: 0;1
                repeatCount: indefinite
                tag: animateMotion
              slots:
                default:
                  - component: f7-row
                    config:
                      tag: mpath
                      xlink:href: "#homeInverter"

I am also not sure what the second component would be to get the >>?

So I tried with:

- component: f7-row
  config:
    d: M80,95 H55 A 10 10 45 0 1 45 90 V70
    fill: none
    id: homeInverter
    stroke: orange
    stroke-width: 2
    tag: path
    vector-effect: non-scaling-stroke
- component: g
  config:
  slots:
   default:
    - component: circle
      config:
        fill: red
        r: 8
        strokeWidth: 10
        vectorEffect: non-scaling-stroke
    - component: circle
      config:
        fill: black
        r: 2
        strokeWidth: 10
        vectorEffect: non-scaling-stroke
      slots:
        default:
          - component: f7-row
            config:
              calcMode: linear
              dur: 3s
              keyPoints: 1;0
              keyPointsReverse: 1;0
              keyTimes: 0;1
              repeatCount: indefinite
              tag: animateMotion
            slots:
              default:
                - component: f7-row
                  config:
                    tag: mpath
                    xlink:href: "#homeInverter"

Which produces:

image

So the first circle is displayed at 0,0 but is not animated. The black circle is animated.

So I am not sure how to add the “>>”. I tried using a - component: text but then nothing displays.

So I am clearly still missing something.

EDIT: Managed to get a square inside a circle:

                                  - component: f7-row
                                    config:
                                      d: M80,95 H55 A 10 10 45 0 1 45 90 V70
                                      fill: none
                                      id: homeInverter
                                      stroke: orange
                                      stroke-width: 2
                                      tag: path
                                      vector-effect: non-scaling-stroke
                                  - component: g
                                    config:
                                    slots:
                                     default:
                                      - component: circle
                                        config:
                                          fill: red
                                          r: 8
                                          strokeWidth: 10
                                          vectorEffect: non-scaling-stroke
                                        slots:
                                          default:
                                            - component: f7-row
                                              config:
                                                calcMode: linear
                                                dur: 3s
                                                keyPoints: 1;0
                                                keyPointsReverse: 1;0
                                                keyTimes: 0;1
                                                repeatCount: indefinite
                                                tag: animateMotion
                                              slots:
                                                default:
                                                  - component: f7-row
                                                    config:
                                                      tag: mpath
                                                      xlink:href: "#homeInverter"                                          
                                      - component: rect
                                        config:
                                          fill: black
                                          r: 2
                                          strokeWidth: 10
                                          vectorEffect: non-scaling-stroke
                                          content: >>
                                          height: 3
                                          width: 3
                                        slots:
                                          default:
                                            - component: f7-row
                                              config:
                                                calcMode: linear
                                                dur: 3s
                                                keyPoints: 1;0
                                                keyPointsReverse: 1;0
                                                keyTimes: 0;1
                                                repeatCount: indefinite
                                                tag: animateMotion
                                              slots:
                                                default:
                                                  - component: f7-row
                                                    config:
                                                      tag: mpath
                                                      xlink:href: "#homeInverter"

CircleSquare

Probably not the most elegant or simple…

Still can get TEXT for the “>>”.

EDIT:

So I now got the “>>”, but no idea how to get the arrows to point in the direction of the animation. Pobably above my skill set:

                                  - component: f7-row
                                    config:
                                      d: M80,95 H55 A 10 10 45 0 1 45 90 V70
                                      fill: none
                                      id: homeInverter
                                      stroke: orange
                                      stroke-width: 2
                                      tag: path
                                      vector-effect: non-scaling-stroke
                                  - component: g
                                    config:
                                    slots:
                                     default:
                                      - component: circle
                                        config:
                                          fill: red
                                          r: 4
                                          strokeWidth: 10
                                          vectorEffect: non-scaling-stroke
                                        slots:
                                          default:
                                            - component: f7-row
                                              config:
                                                calcMode: linear
                                                dur: 3s
                                                keyPoints: 1;0
                                                keyPointsReverse: 1;0
                                                keyTimes: 0;1
                                                repeatCount: indefinite
                                                tag: animateMotion
                                              slots:
                                                default:
                                                  - component: f7-row
                                                    config:
                                                      tag: mpath
                                                      xlink:href: "#homeInverter"                                          
                                      - component: text
                                        config:
                                          text-anchor: middle
                                          x: 0
                                          y: 1.5
                                          content: ">>" 
                                          font-size: 5px
                                        slots:
                                          default:
                                            - component: f7-row
                                              config:
                                                calcMode: linear
                                                dur: 3s
                                                keyPoints: 1;0
                                                keyPointsReverse: 1;0
                                                keyTimes: 0;1
                                                repeatCount: indefinite
                                                tag: animateMotion
                                              slots:
                                                default:
                                                  - component: f7-row
                                                    config:
                                                      tag: mpath
                                                      xlink:href: "#homeInverter" 

Circle--

Nice work. To get the arrows to turn the corner, you’ll need a second animation. In this case you’re not trying to move the animation, you’re trying to rotate it so instead of more animateMotion, you’ll need to use animateTransform:

The only extra tricky part here is that you are going to need to tweak the timing on the transform because you only want it to run for the short period where the group is actually going around the corner, so syncing it up to the motion transform will take a little trial and error.

edit:
Also, you don’t need both the animateMotion blocks that you have if instead of applying them to each element you just apply it to the whole group. That’s the point of using the group in the first place. So, instead of:

group
  circle
    animateMotion
  text
    animateMotion

you can just have

group
  circle
  text
  animateMotion

For the animateTransform, you can also apply it to the group (because you won’t really see it when the circle rotates) or apply it directly to the text instead.

Thanks for the pointer. Will have a look ASAP.

Thanks. I did try that. But had my indentations etc all wrong… Your explanation has made it easier, so I now have:

  - component: f7-row
    config:
      d: M80,95 H55 A 10 10 45 0 1 45 90 V70
      fill: none
      id: homeInverter
      stroke: orange
      stroke-width: 2
      tag: path
      vector-effect: non-scaling-stroke
  - component: g
    slots:
      default:
        - component: circle
          config:
            fill: red
            r: 4
            strokeWidth: 10
            vectorEffect: non-scaling-stroke
        - component: text
          config:
            text-anchor: middle
            x: 0
            y: 1.5
            content: ">>"
            font-size: 5px
        - component: f7-row
          config:
            calcMode: linear
            dur: 3s
            keyPoints: 1;0
            keyPointsReverse: 1;0
            keyTimes: 0;1
            repeatCount: indefinite
            tag: animateMotion
          slots:
            default:
              - component: f7-row
                config:
                  tag: mpath
                  xlink:href: "#homeInverter"

Hope your don’t mind me posting code each time - I just think it helps if anyone else stumbles on this thread and needs help. I have made lots of mistakes on the way and it helps to see working examples too :slight_smile:

Many threads would be easier if more people did this.

So I have been dong some reading and it has become apparent that I first need need to rotate the text 90 degrees so the arrows are initially pointing in the correct direction.

So from what I can see I need to use:

style:
  transform: rotate(90deg)

I guess this would need to be applied to the text component:

  - component: text
    config:
      text-anchor: middle
      x: 0
      y: 1.5
      content: ">>"
      font-size: 5px
      style:
        transform: rotate(90deg)

But I am not getting this to work? Any suggestions please? I have tried with the style and without.

Probably a similar issue to what I had before with the group element.

EDIT: Yip… Indentations again. Edited in code above

Working Mostly

I managed to get the rotation transform most working. It works on teh first run but then gets out of sync.

I think the problem is that I need the rotation transform to begin 2s after the motion starts. Then its runs for 2s and shoudkl then only run when the motions starts at the beginning again (or wait 2s).

But I cannot seem to get this right?

  - component: f7-row
    config:
      d: M80,95 H55 A 10 10 45 0 1 45 85 V70
      fill: none
      id: homeInverter
      stroke: orange
      stroke-width: 2
      tag: path
      vector-effect: non-scaling-stroke
  - component: g
    config:
      visible: true
    slots:
      default:
        - component: circle
          config:
            fill: red
            r: 4
            strokeWidth: 10
            vectorEffect: non-scaling-stroke
        - component: text
          config:
            text-anchor: middle
            x: 0
            y: 2.3
            content: "»"
            font-size: 10px
            style:
              transform: rotate(90deg)
        - component: f7-row
          config:
            dur: 2s
            begin: turn.begin + 2s
            from: 0 0 0
            to: -90 0 0
            repeatCount: indefinite
            tag: animateTransform
            type: rotate
            attributeName: transform
            attributeType: XML
            additive: sum  
            id: move
        - component: f7-row
          config:
            calcMode: linear
            dur: 6s
            keyPoints: 1;0
            keyPointsReverse: 1;0
            keyTimes: 0;1
            repeatCount: indefinite
            tag: animateMotion
            additive: sum
            id: turn
          slots:
            default:
              - component: f7-row
                config:
                  tag: mpath
                  xlink:href: "#homeInverter"

One issue I did run into was that I had to swap the order of the rotation and motion to get them to work.

I have tried combinations of begin and end. But end always seems to break the animation.

Also looking for advice on using different directions of animation. Is it best to setup two animations and just use the visible expression to show which one is shown?

This is why I said this timing was going to be the tricky part. There’s almost certainly an elegant way to do this with begin and end events, but I can’t tell you off the top of my head what that might be. I’d probably just do this the brute force way with a 6s rotation animation that has keyTimes which do the actual animation only during the middle 3rd. That just means you need a 6s duration and values and keyTimes:

keyTimes: 0;.33;.66;1
values: 0;0;-90;-90
duration: 6s

I myself would just expressions in the relevant properties but that would work too. Not sure if one is “best” or not.

Works Perfectly. Thanks so much for your patience and ongoing help.

Working

- component: f7-row
  config:
    d: M80,115 H55 A 10 10 45 0 1 45 105 V80
    fill: none
    id: homeInverter
    stroke: orange
    stroke-width: 2
    tag: path
    vector-effect: non-scaling-stroke
- component: g
  config:
    visible: true
  slots:
    default:
      - component: circle
        config:
          fill: orange
          r: 4
          strokeWidth: 10
          vectorEffect: non-scaling-stroke
      - component: text
        config:
          text-anchor: middle
          x: 0
          y: 2.3
          content: »
          font-size: 10px
          style:
            transform: rotate(90deg)
      - component: f7-row
        config:
          keyTimes: 0;.33;.66;1
          values: 0;0;-90;-90
          dur: 6s                                            
          from: 0 0 0
          to: -90 0 0
          repeatCount: indefinite
          tag: animateTransform
          type: rotate
          attributeName: transform
          attributeType: XML
          additive: sum
          id: turn
      - component: f7-row
        config:
          calcMode: linear
          dur: 6s
          keyPoints: 1;0
          keyPointsReverse: 1;0
          keyTimes: 0;1
          repeatCount: indefinite
          tag: animateMotion
          additive: sum
          id: move
        slots:
          default:
            - component: f7-row
              config:
                tag: mpath
                xlink:href: "#homeInverter"

EDIT - Full Code
Test_SunSynk_Summary_Popup_V1a.txt (22.8 KB)

1 Like