I am trying to animate the result from an oh-repeater component. The oh-repeater is based on an example by JustinG, modified for what I wanted.
The final result will make uses of a nested oh-repeater to generate a list of between 1 and 4 lines, depending on the state of the relevant items based on a group.
I have a working example using the groups, however the animation is inconsistent depending on the number of lines returned.
4 Lines:
1 Line:
I am interested in the “visible display” which will be inside the block.
As you can see, the scrolling looks OK with the full 4 lines, however with 1 line it has a lot of blank space being displayed.
I am looking for a way to make the animation for consistent.
My test code looks like:
uid: filter_demo2
tags: []
props:
parameters:
- context: item
description: Partition ExitDelay Group
label: Partition ExitDelay Group
name: partitionExitDelayGroup
required: false
type: TEXT
parameterGroups: []
timestamp: Feb 25, 2023, 8:18:44 PM
component: f7-block
config:
style:
--f7-block-margin-horizontal: 0px
--f7-block-margin-vertical: 0px
--f7-block-padding-horizontal: 0px
--f7-block-padding-verticall: 0px
border-radius: 5px
height: 90px
justify-content: center
left: 30px
/*overflow: hidden*/
position: absolute
top: 20px
width: 300px
border: 2px solid black
stylesheet: >
.roll_block {
display: block; /* Important to give the content a width */
height: 100%;
overflow: hidden;
position: relative;
/* Add the animation */
animation: move 3s linear infinite /* infinite make reapeat the animation indefinitely */;
} /* Create the animation */ @keyframes move {
from {
translateY(100%);
transform: translateY(100%);}
to {
translateY(-350%);
transform: translateY(-350%); }
}
slots:
default:
- component: oh-repeater
config:
for: exitDelay
sourceType: array
in:
- title: Partition 1 Exit Delay
filter: OFF
- title: Partition 2 Exit Delay
filter: OFF
- title: Partition 3 Exit Delay
filter: OFF
- title: Partition 4 Exit Delay
filter: ON
filter: ({'ON':1,'-':1})[loop.exitDelay.filter]
fragment: true
slots:
default:
- component: Label
config:
class: roll_block
large: true
raised: true
style:
background: var(--paradox-background-color)
color: var(--paradox-font-color)
flex: 0 0 420px
font-size: 25px
font-weight: 700
white-space: nowrap
width: 420px
text: =loop.exitDelay.title
I would appreciate any ideas on how to make this look better?
It appears that to get the animation more consistent the scrolling would need to be applied to an already rendered component with the results from the oh-repeater so that the percentages used to calculate the animation are more accurate? Not sure if this is possible?
I’d say probably only two things that you want to adjust.
You don’t want to be applying the animation to each label separately. You really want one block to keep the visible area cropped and one animated block that has all the content in it. A structure like this:
component: f7-block
- component: f7-block <-- this is roll_block class
- component: oh-repeater
- component: Label
Then you just have to adjust the size of the labels and the animation distance of the single block to get it spaced the way you want. You know that the display area is 90px so you want each of your labels to be that height (assuming that you want only one label to be visible at a time). You just want the animated block to start right at the bottom of the display area so instead of trying to calculate some % you just set the animation transform start at 90px. Similarly you can calculate a better end of the animation transform because you want it to start over as soon as the last text has passed through, not all the space below the last text. That’s 100% less 25px (your defined text height). Css has a calc function that lets you easily combine values with different units so thsi would be calc(-100% + 25px).
Thanks Justin. As usual you are 100% correct. I had tried to do this, but put my block inside the oh-repeater - which clearly was not correct and I ended up with multiple blocks.
I have done some adjustments as per your suggestions (showing block border etc to try get an idea of what is happening):
It looks WAY better, but I still have the issue with the size of the scrolling block when there are less than 4 Labels to display. The block is fixed in size, so the “missing” Labels are replaced by empty space as you can see above.
My current code:
uid: filter_demo2
tags: []
props:
parameters:
- context: item
description: Partition ExitDelay Group
label: Partition ExitDelay Group
name: partitionExitDelayGroup
required: false
type: TEXT
parameterGroups: []
timestamp: Feb 25, 2023, 8:18:44 PM
component: f7-block
config:
style:
--f7-block-margin-horizontal: 0px
--f7-block-margin-vertical: 0px
--f7-block-padding-horizontal: 0px
--f7-block-padding-verticall: 0px
border-radius: 5px
height: 45px
justify-content: center
left: 30px
/*overflow: hidden*/
position: absolute
top: 20px
width: 300px
border: 2px solid black
stylesheet: >
.roll_block {
display: block; /* Important to give the content a width */
height: 100%;
overflow: hidden;
position: relative;
/* Add the animation */
animation: move 5s linear infinite /* infinite make reapeat the animation indefinitely */;
} /* Create the animation */ @keyframes move {
from {
translateY(25px);
transform: translateY(25px);}
to {
translateY(calc(-100% - 25px));
transform: translateY(calc(-100% - 25px)); }
}
slots:
default:
- component: f7-block
config:
class: roll_block
style:
--f7-block-margin-horizontal: 0px
--f7-block-margin-vertical: 0px
--f7-block-padding-horizontal: 0px
--f7-block-padding-verticall: 0px
border-radius: 5px
height: 150px
justify-content: center
left: 0px
/*overflow: hidden*/
position: absolute
top: 20px
width: 300px
border: 2px solid black
slots:
default:
- component: oh-repeater
config:
for: exitDelay
sourceType: array
in:
- title: Partition 1 Exit Delay
filter: OFF
- title: Partition 2 Exit Delay
filter: OFF
- title: Partition 3 Exit Delay
filter: ON
- title: Partition 4 Exit Delay
filter: ON
filter: ({'ON':1,'-':1})[loop.exitDelay.filter]
fragment: true
slots:
default:
- component: Label
config:
class: roll_block1
large: true
raised: true
style:
background: var(--paradox-background-color)
color: var(--paradox-font-color)
flex: 0 0 420px
font-size: 25px
font-weight: 700
white-space: nowrap
width: 420px
text: =loop.exitDelay.title
Any suggestions for making the size of the
Dynamic to match the number of Labels? Or some other “magic”
Why is the box fixed in size? You don’t need or want that. Get rid of the box’s height style and let it set its own height based on how many labels there are.
You still have a ton of extra stuff from your various attempts (happens to me all the time). You should take a few moments to go back and clean up back down to only the bare bones.
This is because you are also setting the height and overflow styles in the roll_block class def and you don’t want either of those.
You don’t need any styles in the roll-block class def (that aren’t directly related to the animations) if you are going to use the style property of the component or vice versa. Here’s another example, you set the position style in under the block component:
Sorry for wasting your time. You were obviously correct. I guess this is a side effect of using examples that may not be 100% relevant but give you the basics that work until you are trying to do something more complex.
Works almost 100% as I wanted now with one small issue that only shows because the block is now a variable size - the speed of the animation becomes unbearably slow with only 1 item (works nicely with 5 seconds for 4 items, but 5 seconds for 1 item is not great…
Do you know if a way to make the following dynamics?
animation: move 5s linear infinite /* infinite make repeat the animation indefinitely */;
I don’t think I can use the oh-repeater loop.variableName_source.length since the block is not a child of the oh-repeater. Any chance you have another solution?
My current code:
tags: []
props:
parameters:
- context: item
description: Partition ExitDelay Group
label: Partition ExitDelay Group
name: partitionExitDelayGroup
required: false
type: TEXT
parameterGroups: []
timestamp: Feb 26, 2023, 9:24:20 AM
component: f7-block
config:
style:
--f7-block-margin-horizontal: 0px
--f7-block-margin-vertical: 0px
--f7-block-padding-horizontal: 0px
--f7-block-padding-verticall: 0px
border: 2px solid black
border-radius: 5px
height: 45px
justify-content: center
left: 30px
overflow: hidden
position: absolute
top: 20px
width: 300px
stylesheet: >
.roll_block {
display: block; /* Important to give the content a width */
overflow: hidden;
/* Add the animation */
animation: move 5s linear infinite /* infinite make repeat the animation indefinitely */;
} /* Create the animation */ @keyframes move {
from {
translateY(0px);
transform: translateY(0px);}
to {
translateY(calc(-100% - 25px));
transform: translateY(calc(-100% - 25px)); }
}
slots:
default:
- component: f7-block
config:
class: roll_block
style:
--f7-block-margin-horizontal: 0px
--f7-block-margin-vertical: 0px
--f7-block-padding-horizontal: 0px
--f7-block-padding-verticall: 0px
/*overflow: hidden*/
border: 2px solid black
border-radius: 5px
width: 300px
justify-content: center
left: 0px
position: absolute
slots:
default:
- component: oh-repeater
config:
filter: ({'ON':1,'-':1})[loop.exitDelay.filter]
for: exitDelay
fragment: true
in:
- filter: ON
title: Partition 1 Exit Delay
- filter: OFF
title: Partition 2 Exit Delay
- filter: OFF
title: Partition 3 Exit Delay
- filter: OFF
title: Partition 4 Exit Delay
sourceType: array
slots:
default:
- component: Label
config:
large: true
raised: true
style:
background: var(--paradox-background-color)
color: var(--paradox-font-color)
flex: 0 0 420px
font-size: 25px
font-weight: 700
white-space: nowrap
width: 420px
text: =loop.exitDelay.title
I really appreciate the time you take to help and explain.
Not easily. This is one of those situations where because the stylesheet is not parsed, the only way to get dynamic values is to use a css variable for the value and set that value dynamically in the style object.
100% correct.
I actually just posted an explanation similar to what you are looking for in another thread:, but it adds a couple levels of component complexity to your widget: