Cases with toggle show/hide remains active for a longer time

Hello, I’m making one of my first prototypes in Axure and I’m now trying to make a 0 to 100% indication that should blink when activated with a button. I made a slider to control the % level between 0 and 100 with steps of 10 which works perfectly.

Now when I activate the blinking the last indication should blink which I made with a series of cases to determine which should be shown based on the % level and then let the last one blink. At first it starts blinking correctly but when I move the slider to change the % level multiple indications start to blink. Also when I deactivate the blinking the indications remain blinking for a longer time. Sometimes they do stop blinking after waiting for a while but I can’t really find out why this happens.

As far as I know I created unique cases with else if statements such that only one should be activated at a time. It does look like multiple cases get enabled and mess up when the blinking is activated. Is there someone who might know what happens here?

Blinking indication.rp (79.7 KB)

The main problem is you’ve assigned your logic to the Page Mouse Move event, so it only gets called when the user moves the mouse, and worse, it gets called multiple times every time the browser detects that the mouse cursor has moved. When a user moves a mouse/trackball it will typically fire this event handler (Page Mouse Move) many many times. Even the shortest possible mouse movement will cover more than 1 px, and thus will likely trigger multiple event calls. The further the travel of the cursor, the more times Page Mouse Move event gets fired. This is why the blinking is erratic and continues long after it should–and eventually stops altogether after the mouse cursor stops moving.

What you need is a reliable timer that continuously checks your variables, at least every 500 ms (the speed of your blink (with fade) animation. In Axure, I’ve found the most reliable method for a timer is to use a Dynamic Panel widget (with at least two states; each can be blank) set to change state every N ms with the repeat setting turned on. When you know this widget will change states exactly every 500 ms then you can use its Panel State Changed event to test things and act accordingly.

In this updated .rp file, I duplicated your “5 Blink Indications” master to “5 Blink Indications (v2)” with these changes:
Blinking indication.rp (97.5 KB)

  • Moved your Interactions logic from Page Mouse Move to the Panel State Changed event of a dynamic panel named “Level Control”.
    • This dp is currently 40x40 px, placed to right of indicators. Because it has no widgets in it, it won’t be visible in the prototype, but will take space in the editor.
    • You can change its size or place behind (or in front) of your indicators if you’d like
  • “Level Control” has a Loaded event that changes its state to “Next, Repeat every 500 ms”. This means it will automatically start your timer loop and keep it running (until you call “Set Panel State to Stop Repeating”
  • I changed the order of your cases and simplified the logic.
    • By first testing the cases when “st_BlinkActv” is true, you can handle these in a more efficient and intuitive “Else If” chain. In other words, after you’ve exhausted all possibilities when this variable is set to “true” then all remaining cases must be when it is false–so you don’t even need to include it in the case logic for your “Indication” cases.
1 Like

Thanks a lot for your extensive reply and updated .rp file. With your setup it works perfect! Only thing is that I tried to decrease the loop time to see if I could get a quicker response. I set the loop time to 100ms instead of 500ms but that lead to the same behavior as the original problem. Do you have any idea why this happens? As far as I could imagine execution of the if else statements should not matter with this loop time but somehow it does seem to skip cases and mess up.

Reason that I would like to decrease the loop time is that I probably build more extended prototypes with different response times of items on the screen. Behavior of the if else conditions would have to be reliable of course.

Best regards.

It is important to realize that commands in Axure–as with most programming languages–are ballistic. Just like throwing a ball or shooting a bullet, once you do it, it goes and you can’t undo it. When you are using motion or animation effects that take time, you need to account for that time or things will get out of sync. The built-in animation effects (you are using the “fade” animation effect) can’t be interrupted or stopped once initiated. (Also realize that “commands” are really just requests --if the system has the resources to perform the action it will, otherwise it may get lost or “ignored.”)

So, if you make a widget hide with a 500 ms fade animation, it will perform that fade over a duration of 500ms, and any actions issued to alter the visibility property during that 500ms won’t take effect until that 500ms elapses. Also, if you issue a chain of actions with animation (of the same property, like visibility) one after the other, they will stack and be performed one after another (or in some cases have no effect.) If you have this sequence of actions:

Hide MyWidget fade 500ms
Wait 100ms
Show MyWidget

…All three actions get fired immediately one after the other–and the “browser graphics engine” handles them in sequence, first by requesting MyWidget be hidden with a fade effect over the course of 500 ms; if MyWidget is ready, it accepts this request and hides. Then a 100 ms timer is started. When that timer elapses, another request is made to show MyWidget–but since MyWidget is busy already, that “show” action doesn’t happen until the ongoing hide animation is completed. So, these three actions would result in MyWidget fading out to fully hidden over the course of 500 ms, then be shown. It would NOT start to hide MyWidget for the first 100 ms then show it at that 100 ms time mark. It would NOT hide MyWidget for 500 ms, then after fully hidden wait 100 ms, then show it --so the whole sequence of events would take about 500 ms, not 600 ms.

Let’s look at the “Level Control” dynamic panel I created and set to repeatedly change states every 500 ms. When st_BlinkAct is set to “true” then the first time it changes states it causes an indicator widget to hide with a 500ms fade animation. The second time it changes states, it shows that indicator, which should be fully hidden because 500ms has elapsed, and so forth. The command to show/hide is synchronized with the change of states (the loop.)

When you made the dp change states every 100 ms, that would result in essentially 5 requests to toggle visibility of a widget over the course of time it takes to perform just one visibility change (hide or show with 500ms fade effect.) So, let’s say you click the “Start Blinking” button and one second later click the “Stop Blinking” button. There would be roughly 10 requests made to show/hide an indicator widget, all of which get stacked up behind each other and performed “when ready” --at 500 ms intervals. Keep in mind, once you invoke these actions they cannot be recalled. So rather than blinking twice, it would blink about 10 times. Likewise, if blinking is on and “ind_1” is set to hide/show, then you move the slider to cause “ind_2” to hide/show that will happen, but “ind_1” would still have lots of requests to hide/show still stacked up, so for awhile both “ind_1” and “ind_2” would blink–depending on how long the slider sat at position 1 before being moved to position 2.

Rather than “skipping cases” the cases are processed properly, but too fast, so their intended actions get caught up in a traffic jam. Going back to my “ballistic ball” metaphor, it is like you’ve dropped a whole bunch of balls down a tube just wide enough to fit one ball. The balls can only get through the end of the tube one at a time, and there’s no way to reach into the tube to pull balls back up.

For your scenario, there are several ways you can try to avoid this traffic jam.

  • Suck it up and live with 500 ms responsiveness :roll_eyes:

  • Keep “Level Control” changing states every 100 ms but process “blinks” only every 5th loop iteration–which should be 500 ms, the same as your show/hide animation fade effect duration.

    • You can do this by incrementing a counter at every loop, then using a modulus function in your case logic.
    • The case logic expression would look like, If [[MyCounter % 5]] equals 0
  • Directly control the “Level Control” dynamic panel with your button clicks and slider moves. Rather than set a global variable and wait for up to 500 ms for “Level Control” to process that change, issue an action to Set Panel State of “Level Control” to next, wrap repeat immediately.

  • Instead of trying to manually control your animations in Axure, create animations in a graphics app, save them as looping animated GIFs and hide/show these with one action instead of a looping series of actions. I think this would be the most reliable way to ensure you are not showing two blinking indicators at once or getting animations out of sync.

    • For example, create an animated GIF for a single blinking indicator. Move it to the same position and in front of the indicator you want to blink and show it.
    • Or, create a dynamic panel with one state per blink/static. With 5 “battery levels” each of which could be static or blinking, this would be 10 states in a dynamic panel.
1 Like

Thanks a lot for all the options. I also understand more of the Axure event logic now. Maybe I expected too much software functionality but with your explanation it makes sense how it reacts.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.