buildrtech/elm-animator-with-elm-css/2.0.0

NOTE: the latest version is 4.0.0

Animator.Timeline

Getting started

elm-animator is about taking pieces of your model, turning them into Timelines of values, and animate between their states

type alias Timeline state =
Timeline state

A timeline of state values.

Behind the scenes this is roughly a list of states and the times that they should occur!

init : state -> Timeline state

Create a timeline with an initial state.

So, if you previously had a Bool in your model:

type alias Model = { checked : Bool }


-- created via
{ checked = False }

You could replace that with an Animator.Timeline Bool

type alias Model = { checked : Animator.Timeline Bool }


-- created via
{ checked = Animator.init False }

Transitioning to a new state

Now that we have a Timeline set up, we likely want to set a new value.

In order to do that we need to specify both —

  • the new state we want to be in
  • a Duration for how long this transition should take.
to : Duration -> state -> Timeline state -> Timeline state

Go to a new state!

You'll need to specify a Duration as well. Try starting with Animator.quickly and adjust up or down as necessary.

type alias Duration =
Duration

Choosing a nice duration can depend on:

  • The size of the thing moving
  • The type of movement
  • The distance it's traveling.

So, start with a nice default and adjust it as you start to understand your specific needs.

Note — Here's a very good overview on animation durations and speeds.

ms : Float -> Duration
update : Posix -> Timeline state -> Timeline state

If you're creating something like a game, you might want to update your Timelines manually instead of using an Animator.

This will allow you to do whatever calculations you need while updating each Timeline.

Note — You'll have to take care of subscribing to Browser.Events.onAnimationFrame.

isRunning : Timeline state -> Bool

Does this timeline have upcoming events?

Note this is only useful if you're not using a Animator.Watcher

Interruptions and Queueing

In some more advanced cases you might want to define a series of states to animate through instead of just going to one directly.

Timeline.interrupt
    [ Timeline.wait (Timeline.millis 300)


    -- after waiting 300 milliseconds,
    -- start transitioning to a new state, Griffyndor
    -- Take 1 whole second to make the transition
    , Timeline.transitionTo (Timeline.seconds 1) Griffyndor


    -- Once we've arrived at Griffyndor,
    -- immediately start transitioning to Slytherin
    -- and take half a second to make the transition
    , Timeline.transitionTo (Timeline.seconds 0.5) Slytherin
    ]
interrupt : List (Step state) -> Timeline state -> Timeline state

Interrupt what's currently happening with a new list.

queue : List (Step state) -> Timeline state -> Timeline state

Wait until the current timeline is finished and then continue with these new steps.

type Step state
wait : Duration -> Step state
transitionTo : Duration -> state -> Step state
scale : Float -> Timeline state -> Timeline state

Speedup or slowdown a timeline.

0.5 -> half speed
1.0 -> normal
2.0 -> twice as fast

Note - 0.1 is the lowest number allowed, and 5 is the highest.

This is generally used in your view function to add a bit of variety when animating multiple elements.

delay : Duration -> Timeline state -> Timeline state

Delay the events of a timeline.

This is generally used in your view function to add a bit of variety when animating multiple elements.

    Animator.move (Animator.delay (Animator.millis 200) timeline) <|
        \state ->
            if state then
                Animator.at 0


            else
                Animator.at 1

This has a maximum value of 5 seconds.

If you need a longer delay, it's likely you want to create a separate timeline.

Reading the timeline

You might be wondering, 'How do we get our value "out" of a Timeline?'

Well, we can ask the Timeline all sorts of questions.

current : Timeline state -> state

Get the current state of the timeline.

This value will switch to a new value when a transition begins.

If you had a timeline that went from A to B to C, here's what current would be at various points on the timeline.

          A---------B---------C
               ^    ^    ^    ^
current:       B    B    C    C

Note — If you want to detect the moment when you arrive at a new state, try using arrivedAt

upcoming : state -> Timeline state -> Bool

Check to see if a state is upcoming on a timeline.

Note — This can be used to ensure a set of states can only be queued if they aren't already running.

Note 2 — This only checks if an event is in the future, but does not check the value you're currently at. You might need to use arrived as well if you also care about the current state.

upcomingWith : (state -> Bool) -> Timeline state -> Bool

For complicated values it can be computationally expensive to use ==.

upcomingWith allows you to specify your own equality function, so you can be smarter in checking how two value are equal.

arrived : Timeline state -> state

Subtley different than current, this will provide the new state as soon as the transition has finished.

          A---------B---------C
               ^    ^    ^    ^
arrived:       A    B    B    C
arrivedAt : state -> Posix -> Timeline state -> Bool

Sometimes we want to know when we've arrived at a state so we can trigger some other work.

You can use arrivedAt in the Tick branch of your update to see if you will arrive at an event on this tick.

Tick time ->
    if Animator.arrivedAt MyState time model.timeline then
        --...do something special
arrivedAtWith : (state -> Bool) -> Posix -> Timeline state -> Bool

Again, sometimes you'll want to supply your own equality function!