This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.
README

Animation

type Animation a = Animation { now : Time, end : Time, f : Time -> a }

An animation describes how a value changes over a finite period of time.

run : Time -> Animation a -> Animation a

Runs an animation for some time. If you need to know when the animation "ends early", leaving time to spare, consider using animate instead.

animate : Time -> Animation a -> ( Animation a, Time )

Like run, but it also includes the amount of time not used up by the animation.

Building

immediately : a -> Animation a

Creates an animation that takes no time and assumes the specified value.

interval : Time -> Animation Float

Runs linearily from 0 to 1 over the time specified.

For negative values you'll get the zero interval.

time : Time -> Animation Time

Runs linearily from 0 to the time specified over the time specified.

For negative values you'll get the zero interval.

Queries

sample : Animation a -> a

Gets the current value of the animation.

timeLeft : Animation a -> Time

The time left until the animation ends.

isDone : Animation a -> Bool

True when the animation is over.

Transforms

reverse : Animation a -> Animation a

Reverses the arrow of time in the animation.

reset : Animation a -> Animation a

Moves the animation back to it's starting point - it's state before it consumed any time.

Combining

append : Animation a -> Animation a -> Animation a

Glues two animations together.

continue : Time -> (a -> Float -> a) -> Animation a -> Animation a

Glues on a new period of time to an animation.

2
    |> Animation.immediately
    |> Animation.continue (2 * Time.second) (\x t -> x + 2 * t)
map : (a -> b) -> Animation a -> Animation b

Builds an animation with the values transformed by a function. If you want to use a function with multiple arguments, you're looking for andMap

andMap : Animation (a -> b) -> Animation a -> Animation b

Applies functions produced by one animation to values produced by another one. In tandem with map, this allows you to combine several animations using a multiple-parameter function.

type alias Position =
    { x : Float, y : Float }

position : Animation Position
position =
    Position `Animation.map` x `Animation.andMap` y

y : Animation Float
y =
    Animation.interval pi
    |> Animation.map cos

x : Animation Float
x = Animation.interval pi
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at http://mozilla.org/MPL/2.0/.


module Animation
    exposing
        ( Animation
        , run
        , animate
        , immediately
        , interval
        , time
        , sample
        , timeLeft
        , isDone
        , reverse
        , reset
        , append
        , continue
        , map
        , andMap
        )

{-|

@docs Animation, run, animate

# Building
@docs immediately, interval, time

# Queries
@docs sample, timeLeft, isDone

# Transforms
@docs reverse, reset

# Combining
@docs append, continue, map, andMap

-}

import Time exposing (Time)


{-| An animation describes how a value changes over a finite period of time.

-}
type Animation a
    = Animation { now : Time, end : Time, f : Time -> a }



-- RUNNING


{-| Runs an animation for some time. If you need to know when the animation
"ends early", leaving time to spare, consider using [`animate`](#animate)
instead.

-}
run : Time -> Animation a -> Animation a
run t ((Animation { now, end, f }) as animation) =
    if t < 0 then
        animation
    else if t < timeLeft animation then
        { now = now + t, end = end, f = f }
            |> Animation
    else
        { now = end, end = end, f = f }
            |> Animation


{-| Like [`run`](#run), but it also includes the amount of time *not* used up by
the animation.

-}
animate : Time -> Animation a -> ( Animation a, Time )
animate t animation =
    if t < timeLeft animation then
        ( run t animation, 0 )
    else
        ( run t animation, t - timeLeft animation )



-- BUILD


{-| Creates an animation that takes no time and assumes the specified value.

-}
immediately : a -> Animation a
immediately value =
    0 |> interval |> map (always value)


{-| Runs linearily from 0 to 1 over the time specified.

For negative values you'll get the zero interval.

-}
interval : Time -> Animation Float
interval t =
    if t < 0 then
        immediately 0
    else
        { now = 0, end = t, f = flip (/) t }
            |> Animation


{-| Runs linearily from 0 to the time specified over the time specified.

For negative values you'll get the zero interval.

-}
time : Time -> Animation Time
time t =
    t |> interval |> map ((*) t)


{-| Glues two animations together.

-}
append : Animation a -> Animation a -> Animation a
append (Animation left) (Animation right) =
    { now = left.now
    , end = left.end + right.end - right.now
    , f =
        \t ->
            if t < left.end then
                left.f t
            else
                right.f <| t - left.end + right.now
    }
        |> Animation


{-| Builds an animation with the values transformed by a function. If you want
to use a function with multiple arguments, you're looking for
[`andMap`](#andMap)

-}
map : (a -> b) -> Animation a -> Animation b
map f (Animation record) =
    { record | f = record.f >> f }
        |> Animation


{-| Applies functions produced by one animation to values produced by another
one. In tandem with [`map`](#map), this allows you to combine several animations
using a multiple-parameter function.

    type alias Position =
        { x : Float, y : Float }

    position : Animation Position
    position =
        Position `Animation.map` x `Animation.andMap` y

    y : Animation Float
    y =
        Animation.interval pi
        |> Animation.map cos

    x : Animation Float
    x = Animation.interval pi


-}
andMap : Animation (a -> b) -> Animation a -> Animation b
andMap (Animation f) (Animation x) =
    let
        ( end, total ) =
            ( f.end `max` x.end
            , f.end - f.now `max` x.end - x.now
            )

        ext =
            extend total >> .f
    in
        { now = 0
        , end = end
        , f = \t -> ext f t <| ext x t
        }
            |> Animation


extend :
    Time
    -> { now : Time, end : Time, f : Time -> a }
    -> { now : Time, end : Time, f : Time -> a }
extend to anim =
    { anim
        | end = anim.now + to
        , f =
            \t ->
                anim.f
                    (if t <= anim.end then
                        t
                     else
                        anim.end
                    )
    }


{-| Reverses the arrow of time in the animation.

-}
reverse : Animation a -> Animation a
reverse (Animation { now, end, f }) =
    { now = end - now
    , end = end
    , f = \t -> f (end - t)
    }
        |> Animation


{-| Moves the animation back to it's starting point - it's state before it
consumed any time.

-}
reset : Animation a -> Animation a
reset (Animation { end, f }) =
    { now = 0
    , end = end
    , f = f
    }
        |> Animation


{-| Glues on a new period of time to an animation.

    2
        |> Animation.immediately
        |> Animation.continue (2 * Time.second) (\x t -> x + 2 * t)

-}
continue : Time -> (a -> Float -> a) -> Animation a -> Animation a
continue t startWith prefix =
    let
        suffix =
            t
                |> interval
                |> map
                    (prefix
                        |> run (timeLeft prefix)
                        |> sample
                        |> startWith
                    )
    in
        prefix `append` suffix



-- QUERY


{-| Gets the current value of the animation.

-}
sample : Animation a -> a
sample (Animation { now, f }) =
    f now


{-| True when the animation is over.

-}
isDone : Animation a -> Bool
isDone (Animation { now, end }) =
    now == end


{-| The time left until the animation ends.

-}
timeLeft : Animation a -> Time
timeLeft (Animation { now, end }) =
    end - now