This module provides a variety of interpolation methods for blending between two values. While primitives for numbers, colors and lists are provided, the library focuses on composition so that you can build interpolators for your own custom datatypes.
Basics.Float -> a
An interpolator is merely a function that takes a float parameter t
roughly in the range [0..1].
0 would represent the "before" value, 1 the after value and values in between are the values in between.
Note: Sometimes the range of the interpolator can go slightly above or below zero - this is useful for some animation techniques. If this is not suitable for your data type, remember to clamp the values as necessary.
float : Basics.Float -> Basics.Float -> Interpolator Basics.Float
Interpolates between the two provided float values.
myInterpolator : Interpolator Float
myInterpolator = Interpolation.float 5 17
myInterpolator 0.2 -- 7.4
myInterpolator 0.5 -- 11
int : Basics.Int -> Basics.Int -> Interpolator Basics.Int
Interpolates between ints.
step : a -> List a -> Interpolator a
Interpolate between arbitrary values by just showing them in sequence.
The list is provided is passed as head and tail seperately, to avoid needing to handle the empty list case.
type StageOfGrief
= Denial
| Anger
| Bargaining
| Depression
| Acceptance
griefInterpolator : Interpolator StageOfGrief
griefInterpolator =
Interpolation.step Denial
[ Anger
, Bargaining
, Depression
, Acceptance
]
griefInterpolator 0 --> Denial
griefInterpolator 0.5 --> Bargaining
griefInterpolator 1.1 --> Acceptance
rgb : Color -> Color -> Interpolator Color
Interpolates between two Color values using the sRGB color space.
rgbWithGamma : Basics.Float -> Color -> Color -> Interpolator Color
Interpolates between two Color values using the sRGB color space using gamma correction.
hsl : Color -> Color -> Interpolator Color
Interpolates between two Color values using the HSL color space. It will always take the shortest path between the target hues.
hslLong : Color -> Color -> Interpolator Color
Like Interpolation.hsl
, but does not use the shortest path between hues.
lab : Color -> Color -> Interpolator Color
Interpolates between two Color values using the CIELAB color space, that is more perceptually linear than other color spaces. Perceptually linear means that a change of the same amount in a color value should produce a change of about the same visual importance. This property makes it ideal for accurate visual encoding of data.
hcl : Color -> Color -> Interpolator Color
Interpolates between two Color values using the CIE Lch(ab) color space.
hclLong : Color -> Color -> Interpolator Color
Like hcl, but does not use the shortest path between hues.
map : (a -> b) -> Interpolator a -> Interpolator b
Transform values from another interpolator.
Note: This function is provided as a convenience, since thinking in mapN
is pretty natural for Elm developers (and
works well in pipelines). However, keep in mind that this function is literally an alias for <<
.
map2 : (a -> b -> c) -> Interpolator a -> Interpolator b -> Interpolator c
Combine two interpolators, combining them with the given function.
type alias Coords =
( Float, Float )
interpolateCoords : Coords -> Coords -> Interpolator Coords
interpolateCoords ( x1, y1 ) ( x2, y2 ) =
Interpolation.map2
Tuple.pair
(Interpolation.float x1 x2)
(Interpolation.float y1 y2)
map3 : (a -> b -> c -> d) -> Interpolator a -> Interpolator b -> Interpolator c -> Interpolator d
map4 : (a -> b -> c -> d -> e) -> Interpolator a -> Interpolator b -> Interpolator c -> Interpolator d -> Interpolator e
map5 : (a -> b -> c -> d -> e -> f) -> Interpolator a -> Interpolator b -> Interpolator c -> Interpolator d -> Interpolator e -> Interpolator f
piecewise : (a -> a -> Interpolator a) -> a -> List a -> Interpolator a
Returns a piecewise interpolator, composing interpolators for each adjacent pair of values.
For example:
myInterpolator : Interpolator Int
myInterpolator =
Interpolation.piecewise Interpolation.int 6 [ 10, -2 ]
myInterpolator 0 --> 6
myInterpolator 0.25 --> 8
myInterpolator 0.5 --> 10
myInterpolator 0.75 --> 4
myInterpolator 1 --> -2
tuple : (a -> a -> Interpolator a) -> (b -> b -> Interpolator b) -> ( a, b ) -> ( a, b ) -> Interpolator ( a, b )
Composes interpolators around a tuple. This is a convenience function for the common case of 2 element tuples.
You can for example define an interpolator for a position:
interpolatePosition : ( Float, Float ) -> ( Float, Float ) -> Interpolator ( Float, Float )
interpolatePosition =
Interpolation.tuple Interpolation.float Interpolation.float
inParallel : List (Interpolator a) -> Interpolator (List a)
This will run all of the interpolators provided in parallel.
Can be handy for constructing complex interpolations in conjuction with List.map2
:
before : List Float
before =
[ 3, 4, 7, 8 ]
after : List Float
after =
[ 6, 4, 1, 9 ]
myInterpolator0 : Interpolator (List Float)
myInterpolator0 =
List.map2 Interpolation.float before after
|> Interpolation.inParallel
myInterpolator0 0 --> [ 3, 4, 7, 8 ]
myInterpolator0 0.5 --> [ 4.5, 4, 4, 8.5]
myInterpolator0 1 --> [ 6, 4, 1, 9 ]
staggeredWithParallelism : Basics.Float -> List (Interpolator a) -> Interpolator (List a)
Combines a bunch of interpolators with a controlled amount of parallelism.
Let's illustrate what we mean by showing an example:
interpolate : Float -> Interpolator (List Int)
interpolate parallelism =
List.repeat 5 (Interpolation.int 0 8)
|> Interpolation.staggeredWithParallelism parallelism
Now when the parallelism is 1, we will run each interpolator when the previous one concludes:
Interpolation.samples 11 (interpolate 1)
--> [ [ 0, 0, 0, 0, 0 ]
--> , [ 4, 0, 0, 0, 0 ]
--> , [ 8, 0, 0, 0, 0 ]
--> , [ 8, 4, 0, 0, 0 ]
--> , [ 8, 8, 0, 0, 0 ]
--> , [ 8, 8, 4, 0, 0 ]
--> , [ 8, 8, 8, 0, 0 ]
--> , [ 8, 8, 8, 4, 0 ]
--> , [ 8, 8, 8, 8, 0 ]
--> , [ 8, 8, 8, 8, 4 ]
--> , [ 8, 8, 8, 8, 8 ]
--> ]
If we set it to 2, we will start each interpolator approximately halfway through the previous one:
Interpolation.samples 11 (interpolate 2)
--> [ [ 0, 0, 0, 0, 0 ]
--> , [ 2, 0, 0, 0, 0 ]
--> , [ 5, 1, 0, 0, 0 ]
--> , [ 7, 3, 0, 0, 0 ]
--> , [ 8, 6, 2, 0, 0 ]
--> , [ 8, 8, 4, 0, 0 ]
--> , [ 8, 8, 6, 2, 0 ]
--> , [ 8, 8, 8, 5, 1 ]
--> , [ 8, 8, 8, 7, 3 ]
--> , [ 8, 8, 8, 8, 6 ]
--> , [ 8, 8, 8, 8, 8 ]
--> ]
If we set it to 1/2, we will wait approximately the time a single interpolator runs after each run doing nothing (slightly more samples so it's easier to see what's going on):
Interpolation.samples 16 (interpolate 0.5)
--> [ [ 0, 0, 0, 0, 0 ]
--> , [ 5, 0, 0, 0, 0 ]
--> , [ 8, 0, 0, 0, 0 ]
--> , [ 8, 0, 0, 0, 0 ]
--> , [ 8, 3, 0, 0, 0 ]
--> , [ 8, 8, 0, 0, 0 ]
--> , [ 8, 8, 0, 0, 0 ]
--> , [ 8, 8, 2, 0, 0 ]
--> , [ 8, 8, 6, 0, 0 ]
--> , [ 8, 8, 8, 0, 0 ]
--> , [ 8, 8, 8, 0, 0 ]
--> , [ 8, 8, 8, 5, 0 ]
--> , [ 8, 8, 8, 8, 0 ]
--> , [ 8, 8, 8, 8, 0 ]
--> , [ 8, 8, 8, 8, 3 ]
--> , [ 8, 8, 8, 8, 8 ]
--> ]
As parallelism approaches infinity, than this will behave like Interpolation.inParallel
.
If thinking about this in terms of parallelism doesn't feel natural, you may appreciate Transition.stagger
which deals
with durations and delays instead.
list : { add : a -> Interpolator a, remove : a -> Interpolator a, change : a -> a -> Interpolator a, id : a -> comparable, combine : ListCombiner } -> List a -> List a -> Interpolator (List a)
This is an interpolator for lists. It is quite complex and should be used if these conditions hold:
.id
member, which is comparable
.The first argument is a configuration record. It has the following keys:
id : a -> comparable
is a function that retrieves some sort of identifier for each item in the list. It is used to figure out if an item is added, removed, or modified.add : a -> Interpolator a
will be invoked for each item being added to the list.remove : a -> Interpolator a
will be invoked for each item disappearing from the list. Note that the item won't actually be removed from the list until t = 1
, so you will most likely want to make the item disappear visually.change : a -> a -> Interpolator a
is called for an item where the id
matches for both lists, but which are not equal.combine : ListCombiner
configures a strategy that orchestrates all the interpolations created. At the moment only 'combineParallel' is supported, but staggered transitions will be supported in the future.combineParallel : ListCombiner
Runs all the list interpolations in parallel.
pointAlongPath : Path -> Interpolator ( Basics.Float, Basics.Float )
A somewhat elaborate interpolator that gives points along an arbitrary path, where at t=0
this will give the first point in the path,
and at t=1
gives the last. If overshot, will give points along the tangent at these points.
Will give the origin point if the path is empty or invalid (generally you should check somewhere earlier if there is a possibility of that).
Performance note: this function does a fair amount of work when the interpolator is being constructed, so that later when it is called with
the t
parameter it can be rather efficient. Therefore it is more efficient to partially apply this with a path in a static context or store
the partially applied function in a model.
samples : Basics.Int -> Interpolator a -> List a
Returns a list of uniformly spaced samples from the specified interpolator. The first sample is always at t = 0, and the last sample is always at t = 1. This can be useful in generating a fixed number of samples from a given interpolator.
Can be quite handy when debugging interpolators or as a way to create a quantize scale.