When scheduling animations very quickly (i.e. with touch events), sometimes they get into the same cycle (i.e. multiple scheduled before Tick occurs). Due to the current implementation of applying interruptions, there is a possible scenario when touchMove animation happens after touchEnd.
Open Chrome Dev Tools && Device Toolbar (to get mobile touch events)
Start moving the Box down. (Do it number of times to get the described scenario)
Expected behaviour: box follows the move and on release returns to original position.
Wrong behaviour: box gets stuck at the last touchMove position, instead of returning back.
Why it happens?
When applying Interruptions, they are applied as LIFO (Last-in-First-Out). This sometimes results in touchEnd being applied first, and then touchMove. Because of this final position is touchMove, instead of touchEnd.
applyInterruptionHelper : List (Schedule event) -> TimelineDetails event -> TimelineDetails event
applyInterruptionHelper interrupts timeline =
case interrupts of
[] ->
timeline
inter :: remaining ->
let
delay =
case inter of
Schedule d _ _ ->
d
newEvents =
interrupt timeline (Time.advanceBy delay timeline.now) inter
in
applyInterruptionHelper remaining { timeline | events = newEvents }
Possible solution
I have tried reversing the list, before applying it, so that we follow a FIFO (First-in-First-Out) strategy. So that, we apply events in the same order as they arrived into schedule. Like so in src/Internal/Timeline.elm:
Problem
When scheduling animations very quickly (i.e. with touch events), sometimes they get into the same cycle (i.e. multiple scheduled before Tick occurs). Due to the current implementation of applying interruptions, there is a possible scenario when touchMove animation happens after touchEnd.
How to reproduce?
Start moving the Box down. (Do it number of times to get the described scenario) Expected behaviour: box follows the move and on release returns to original position. Wrong behaviour: box gets stuck at the last touchMove position, instead of returning back.
Why it happens?
When applying Interruptions, they are applied as LIFO (Last-in-First-Out). This sometimes results in touchEnd being applied first, and then touchMove. Because of this final position is touchMove, instead of touchEnd.
Possible solution
I have tried reversing the list, before applying it, so that we follow a FIFO (First-in-First-Out) strategy. So that, we apply events in the same order as they arrived into schedule. Like so in
src/Internal/Timeline.elm
:This seems to solve the issue.
Questions
Others
Original description: slack