Giter Site home page Giter Site logo

mdgriffith / elm-style-animation Goto Github PK

View Code? Open in Web Editor NEW
443.0 22.0 41.0 971 KB

The style animation library for Elm!

Home Page: http://package.elm-lang.org/packages/mdgriffith/elm-style-animation/latest

License: BSD 3-Clause "New" or "Revised" License

Elm 100.00%
animation elm spring elm-style-animation

elm-style-animation's Introduction

The Style Animation library for Elm!

The Basics

To get started, there are a few things that need to happen.

Set an initial style in your model.

import Animation exposing (px)

init : Model
init =
    { style = 
        Animation.style
            [ Animation.left (px 0.0)
            , Animation.opacity 1.0
            ]
    }

Subscribe to Animation's subscription. This will animate using AnimationFrame when something is running, and stop giving updates when there is no animation.

subscriptions : Model -> Sub Msg
subscriptions model =
    Animation.subscription Animate [ model.style ]

Set up an update Msg in your update function.

    Animate animMsg ->
        { model
            | style = Animation.update animMsg model.style
        }

Render our animation at the necessary element in your view. Not all animated properties are style properties(such as the svg.d property and polygon.points property), so Animation.render actually returns a list of Html.Attributes. Fortunately, you can add your own style because Html.Attributes.style stacks!

    div
        (List.concat
            [ Animation.render model.style
            , [ style
                    [ ( "position", "absolute" )
                    , ( "border-style", "dotted" )
                    ]
               ]
            ]
        )
        [ text "This is being Animated!" ]

Start an animation in your update statement.

case msg of
    Show ->
        let 
            newStyle = 
                Animation.interrupt
                    [ Animation.to 
                        [ Animation.left (px 0.0)
                        , Animation.opacity 1.0
                        ]
                    ]
                    model.style
        in
            { model
                | style = newStyle
            }

Here's generally how we compose animations.

  • Choose Animation.queue or Animation.interrupt, both of which take a list of steps and your animation model. This describes what the strategy should be if the thing you're trying to animate is already in the process of being animated. You either want to interrupt what its doing and do this new animation. Or you want to queue up this new animation to run after the current animation is finished. 90% of the time you want Animation.interrupt
  • Steps can be
    • Animation.to - Animate to a target style
    • Animation.set - Set a animation to a style immediately.
    • Animation.wait (5 * second) - wait for some amount of time
    • Animation.repeat x [..list of steps to repeat] - Repeat a list of steps x times.
    • Animation.loop [..list of steps to repeat] - Loop a list of steps forever/until interrupted.

Examples

Advanced!

Note!

The compiler is going to refer to your animation model as Animation.Model.Animation msg. Animation.State is just a synonym for that.

Sending Messages

  • Send Messages Example - Code

First, import Animation.Messenger

Change your Animation.State to Animation.Messenger.State MyMsgType.

You can now use Animation.Messenger.send MyCustomMessage as a step in composing your animation.

You need to update this new animation state using Animation.Messenger.update, which will return (newAnimState, messagesSentinCmdForm). So you need to change your animation update section to something like the following.

case msg of
    Animate animMsg ->
        let
            (newStyle, cmds) =
                Animation.Messenger.update
                    animMsg
                    model.style
        in
            ( { model
                 | style = newStyle
              },
              cmds
            )

Note! Make sure you're sending the cmds in the above code. If you're note, then the animation will run, but the messages won't be sent.

Also, if you're running this in a child component, make sure you're Cmd.maping the child's commands back to the child or else the messages will be lost!

Animating Properties that aren't directly supported.

You can construct custom properties if you don't find them in the library using Animation.custom. These will be rendered in the style property.

Animation.to
    [ Animation.custom "my-custom-prop" 5 "px"
    ]

There is also customColor for color based properties.

Setting Custom Interpolation

Behind the curtain elm-style-animation mostly uses springs to animate values from A to B. However you can specify custom values for a spring, or a duration and easing if you want. There are two basic ways to do this.

Set them with your initial style.

Use Animation.styleWith or Animation.styleWithEach to set your initial style instead of Animation.style.

Animation.styleWith
    (Animation.spring
        { stiffness = 400
        , damping = 23 }
    )
    [ Animation.opacity 0
    , Animation.left (px 20)
    ]

This will set the spring used for these properties. Alternatively Animation.styleWithEach is a way to set a custom interpolation for each individual property.

Set a temporary spring/duration + easing

You can also use Animation.toWith and Animation.toWithEach. These can be substituted for Animation.to and allow you to specify a spring or duration+easing that lasts for exactly one step. After that step, whatever default spring or duration/easing there is (either the auto default or via being specified in Animation.styleWith) is then used.

Animation.interrupt
    [ Animation.toWith
        (Animation.easing
            { duration = 2*second
            , ease = (\x -> x^2)
            }
        ) 
        [ Animation.left (px 0.0)
        , Animation.opacity 1.0
        ]
    ]
    model.style

elm-style-animation's People

Contributors

guid75 avatar mdgriffith avatar trotha01 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elm-style-animation's Issues

Function `to` is expecting the argument to be: Float

When I try to compile my app, I get the following error:

The 1st argument to function `interrupt` is causing a mismatch. - Function `interrupt` is expecting the 1st argument to be:

    List (Animation.Model.Step msg)

But it is:

    List (Animation.Animation -> Animation.Animation)

Hint: It looks like a function needs 1 more argument.
~~~
List (Animation.Model.Step msg) -> Animation.Model.Animation msg -> Animation.Model.Animation msg
~~~

 Interrupt any running animations with the following animation.

The code is
newModel = { model | cardStyle = Animation.interrupt [ Animation.to styles.disliked ] model.cardStyle }
type alias Model = { ... , cardStyle : Animation.State }
styles = { disliked = [ Animation.left (px -100.0) , Animation.opacity 0 ] , normal = [ Animation.left (px 0) , Animation.opacity 1.0 ] }

Any ideas?

Best

Multiple animations affecting the same property fail

I posted this in the Elm Slack #animations channel, but I think it warrants an issue for improvement.

In particular, it would be helpful to log a warning if a list of animations updating a property happen to update the same property from two different animations, like is already done on creation of a single animation modifying the same property multiple times.

It also feels a bit like a bug that a completed animation (running=False) could take priority for a property value that is being changed by a still-in-progress animation. I'm not sure what to suggest there (whether a code change, or just highlighting it in the docs, if a code change is too difficult or unreasonable for the package expectations). I could see that going either way.

Here are my comments from the Slack channel, for context (with the link updated to the particular commit at the time). First, the problem I ran into, then the solution.

I’m struggling a bit with performing a couple of chained commands in a simple animation demo. It looks simple enough and I think I’m chaining them correctly, but it seems like my model state isn’t being maintained correctly.

Could someone take a look and point out where I’m losing the model state? I can’t seem to find it.

Link: stormont/elm-animation-examples@0af75f8

I’m trying to get a click on one box to get it to fade out, while fading in the other box at the same time, so that there’s always only one box to click. Ignoring the separate problem that both are visible at app start (an intentional debugging change I currently have in place), I can’t seem to get commands to update the model state for both boxes simultaneously, despite seeing both animations running in the Explore History debugger.

The problem (symptom?) is in the SwapView command. It’s trying to execute an animation on one view, then execute a different animation on a different view, and it naively appears to be chaining the models correctly, as far as I can tell. But, when you run the code, you’ll see that clicking on either box (view) only animates that box, not the other one as well.

I feel like I’m missing something very small, but I can’t put my finger on it. The problem seems to be unrelated to the actual act of animation and more related to the problem of chaining commands/models.

Supposed to animate both at once.

If you make the animation identifier “fade_out_fade_in” on both, you’ll see them both animate.

But when they start from different states, I seem to get different variations of behaviors.

Also, everything seems to work individually up to this point, but chaining the two commands together makes them go wonky.

Actually, I take that back. If I start both elements from an opacity of 0 and try to just (ExecuteAnimation "ElementX" "fade_in") when clicking on either one, I can’t get them to fade in, either. Definitely seems like some oddness around opacity there.

Maybe having an animation end at 0 opacity causes some other display side effect? I wouldn’t think so, because you can still click the element and see messages being logged.

And the solution I eventually found:

For anyone that cares, I was able to root out the problem. It was a combination of my code plus a nuance of the animations package.

The animations package will only use the last defined instance of any property. If you directly try to use the same property twice in an animation definition, it will console log a warning, but my case was obscuring this. My code here is intentionally trying to make the animations more composable, but that avoids the check for the double-definitions.

Basically, it's possible to have two different animations running (or even set to "not running"/completed) that affect the same property. In that case, only one will actually run (even if the chosen animation has already completed).

As opposed to one animation affecting the same property in two ways, which is what the console log checks for.

I avoided the issue in my code by making sure I only ever had one particular animation defined at a time on a given view element, which makes intuitive sense. But, it took me a few days to track the problem down. Others might have the same problem.

Style attribute in svg not rendered in firefox

See example program in gist

When I open the program (in elm reactor or compile it using elm make Main.js) in google-chrome, it works fine (mouse over the circle to see it move).

But when I run it in firefox (v 47, running on Fedora 22), the style attribute of circle is not rendered at all (so the circle doesn't move). Is this a bug or am I doing something wrong?

Animating z-index

Hi,

I couldn't find a way to change value of z-index as part of api.
I have tried Animation.exact "z-index" "2" but it didn't apply on interrupt animations.

Did you had a reason to opt it out?

I can make a PR if you are ok with it.

Cheers

Animation steps after 'repeat' never happen

It seems repeat prevents subsequent steps from animating?

Animation.interrupt
    [ Animation.to
        [ Animation.rotate (turn 0.5) ]
    -- steps before repeat work fine, as expected
    , ( Animation.repeat 3
        [ Animation.to
            [ Animation.translate (px 0) (px 150) ]
        , Animation.to
            [ Animation.translate (px 0) (px 0) ]
        ] )
    -- steps after repeat never happen
    , Animation.to
        [ Animation.rotate (turn 0.0) ]
    ]

I can't break out styles into composable functions

instead of {style = Animation.style [ Animation.left (px 0.0) ]} I want to break but styles into helper functions. I need to do this in order to dynamically style each element so I set up a function like this:

layoutStyles : ElementId -> Animation a
layoutStyles id =
    Animation.style [ Animation.left (0 * id |> px) ]

initModel id =
    {style = layoutStyles id}

but I get the following error:

Cannot find type `Animation`

25| layoutStyles : Maybe Int -> Animation a
                               ^^^^^^^^^

And when I try Animation.State I get a type mismatch. Because Elm infers that it's looking for Animation.Model.Animation a and I have no way of getting to that type as far as I know.

IE9 Compatibility

Hello!

I noticed this library doesn't work with IE9
That's fine, because I can easily provide fallback content.
But, just out of curiosity, I was wondering why?
Does elm-html-animation use CSS transitions and animation under-the-hood (IE9 doesn't support those)?

Expose `Animate.Msg` fuzzer.

We are using this library for animations. It's great, thanks! We also use ArchitectureTest to test updates. It requires a message fuzzer to generate a list of random messages which could be applied sequentially and return new model. It would be nice to expose Animation.Msg fuzzer in order to generate random animation messages. Please let me know if it makes sense and if you would like me to do a PR for it?

Add type to the docs

It should be a good idea to add the Animation.State to the docs because the compiler is suggesting something totally different: Animation.Model.Animation msg. I had to look in one of your repos to figure out the type.

toWith not firing

The toWith function isn't working correctly for me. I made a demo app to illustrate the issue:

Desired functionality

  • Ball starts blue
  • When hovering, ball quickly turns orange (easing of 0.2 seconds)
  • When unhovering, ball slowly turns blue (easing of 1 second)

Actual functionality

  • When unhovering, ball usually does not turn blue. It only turns blue if I quickly hover and unhover within 0.2 seconds (the default easing time).

demo3

module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Animation exposing (px)
import Color
import Time


main : Program Never Model Msg
main =
    Html.program
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }


type alias Model =
    { ball : Animation.State }


init : ( Model, Cmd Msg )
init =
    ( { ball =
            Animation.styleWith
                -- default easing is 0.2 seconds
                (Animation.easing
                    { duration = 0.2 * Time.second
                    , ease = (\x -> x)
                    }
                )
                [ Animation.backgroundColor (Color.blue)
                ]
      }
    , Cmd.none
    )


subscriptions : Model -> Sub Msg
subscriptions model =
    Animation.subscription Animate [ model.ball ]


type Msg
    = MouseEnter
    | MouseLeave
    | Animate Animation.Msg


update : Msg -> Model -> ( Model, Cmd Msg )
update action model =
    case action of
        MouseEnter ->
            -- use default easing of 0.2 seconds
            ( { model
                | ball =
                    Animation.interrupt
                        [ Animation.to
                            [ Animation.backgroundColor (Color.orange)
                            ]
                        ]
                        model.ball
              }
            , Cmd.none
            )

        MouseLeave ->
            -- use new easing of 1 second
            ( { model
                | ball =
                    Animation.interrupt
                        [ Animation.toWith
                            (Animation.easing
                                { duration = 1 * Time.second
                                , ease = (\x -> x)
                                }
                            )
                            [ Animation.backgroundColor (Color.blue)
                            ]
                        ]
                        model.ball
              }
            , Cmd.none
            )

        Animate animMsg ->
            ( { model | ball = Animation.update animMsg model.ball }, Cmd.none )


view : Model -> Html Msg
view model =
    div
        (Animation.render model.ball
            ++ [ onMouseEnter MouseEnter
               , onMouseLeave MouseLeave
               , style
                    [ ( "width", "200px" )
                    , ( "height", "200px" )
                    , ( "border-radius", "100%" )
                    , ( "margin", "200px auto" )
                    , ( "cursor", "pointer" )
                    , ( "text-align", "center" )
                    ]
               ]
        )
        []

Unable to define types in application code

Hi,

It looks like elm-style-animation does not export the various types the library uses internally, e.g Animation and various things from Animation.Model. While the examples in examples/ work fine, some top-level definitions lack type annotations.

I compile all my Elm code with --warn turned on. The compiler warns me about missing type annotations, and even offers inferred ones, but I'm unable to do anything, because I'm unable to import the necessary bits.

Would it be possible to "open up" the types slightly? Perhaps in the next version? Or maybe there is an alternative solution?

Thanks!

Need help with animating a path

Hi, great project, I'm very excited to use it!
I need some help with animating a path, I can't seem to make it work.
I've copied my best guess as how it should work below, but when I run it, only one ticks happens and nothing shows up.
Thanks!

module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Animation
import Svg
import Svg.Attributes


main : Program Never Model Msg
main =
    Html.program
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }


type alias Model =
    { style : Animation.State }


init : ( Model, Cmd Msg )
init =
    ( startAnimation
        { style =
            Animation.style
                [ Animation.path [ Animation.moveTo 0 0 ] ]
        }
    , Cmd.none
    )


subscriptions : Model -> Sub Msg
subscriptions model =
    Animation.subscription Animate [ model.style ]


type Msg
    = Animate Animation.Msg


update : Msg -> Model -> ( Model, Cmd Msg )
update action model =
    case action of
        Animate animMsg ->
            ( { model | style = Animation.update animMsg model.style }
            , Cmd.none
            )


startAnimation : Model -> Model
startAnimation model =
    { model
        | style =
            Animation.queue
                [ Animation.to
                    [ Animation.path
                        [ Animation.lineTo 200 200
                        , Animation.lineTo 200 100
                        , Animation.close
                        ]
                    ]
                ]
                model.style
    }


view : Model -> Html Msg
view model =
    Svg.svg
        [ Svg.Attributes.width "300"
        , Svg.Attributes.height "300"
        ]
        [ Svg.path
            (Animation.render model.style
                ++ [ Svg.Attributes.d "M 0 0 "
                   , Svg.Attributes.stroke "red"
                   ]
            )
            []
        ]

Support for content animations

We’re about to build a feature that requires “content” animations, not just style animations, and we’re wondering how far elm-style-animation is from being able to support this. Would it make sense to try to contribute support for this to elm-style-animation, or is the problem sufficiently different that you’d encourage us to solve it in a separate library?

Specifically, we’d like to animate a bar graph so that the height of each bar grows to its assigned size, while at the same time a number that labels the bar counts up. Both the height of the bar and the current count should be animated with the same spring “physics”.

This is relatively straightforward in react-motion, which we’ve used before. From the README:

import {Motion, spring} from 'react-motion';
// In your render...
<Motion defaultStyle={{x: 0}} style={{x: spring(10)}}>
  {value => <div>{value.x}</div>}
</Motion>

elm-style-animation does a really nice job of abstracting away the details of animating styles between values, but we wonder if it might be possible to also expose arbitrary integers like these (Animation.int, perhaps?), which could then be used to generate content, in addition to styles, in our views.

Thanks for any advice you may provide!

source code learning, some question

Hi, i'm wirting a framework for elm, want Integrate elm-style-animation
i read code ,and have some question:

  • in the resolveSteps

the Step -> already did List.all isDone stepped ,
why To target -> do same by alreadyThere? both run function: step dt props , i think it's unnecessary ,can you explain this?

  • in alreadyThere ,

why use step 0 ,is that step 16.666 do same thing?

Unable to define custom color property

I have an SVG that uses a linearGradient def as its fill. Now I want to animate that linearGradient, but the properties are not in the list of exposed functions in elm-style-animation. If the function colorProp were exposed, I could do this as I wanted without exposing the Property type.

Would there be any objection to the idea of exposing colorProp?

Update elm-community/list-extra

Right now I can't install mdgriffith/style-elements with mdgriffith/elm-style-animation, i.e.

cd /tmp
mkdir test
cd test
elm-package install mdgriffith/style-elements
elm-package install mdgriffith/elm-style-animation

screen shot 2017-02-13 at 2 35 26 pm

I believe this is because of "elm-community/list-extra. The current version is:

To install elm-community/list-extra I would like to add the following
dependency to elm-package.json:

    "elm-community/list-extra": "6.0.0 <= v < 7.0.0"

May I add that to elm-package.json for you? [Y/n] 

https://github.com/mdgriffith/elm-style-animation/blob/master/elm-package.json#L15:

"elm-community/list-extra": "5.0.0 <= v < 6.0.0",

@see mdgriffith/style-elements#7

Separate module for SVG properties?

Re: SVG height and width attributes #27

Stumbled over this again after a long break from animations (and because both Chrome and Safari will interpret a height style as an attribute).

Perhaps it would best to separate SVG attributes/styles from HTML ones? (Keeping the current ones in Animation for backwards compatibility?)

There's a note in #27 about producing both style and attribute values. I think I'd prefer the separate modules to reduce the chance that I'll once again accidentally use something that applies to HTML thinking it applies to SVG.

Expose `isRunning`?

Would you be open to exposing the isRunning function? My use case is, that when an animation has finished (i.e. opacity 1 → opacity 0), then I'd like to hide the element. To do that I need to know when the animation has finished.

I tried animating the DisplayMode property from noneblock, but it didn't work, as the display property was never changed.

        Animation.styleWith
            (Animation.easing
                { duration = 400 * Time.millisecond
                , ease = identity
                }
            )
            [ Animation.opacity 0.0, Animation.display Animation.none ]
                            Animation.interrupt
                                [ Animation.to
                                    [ Animation.opacity 0
                                    , Animation.display Animation.none
                                    ]
                                ]
                    Animation.interrupt
                        [ Animation.to
                            [ Animation.opacity 1
                            , Animation.display Animation.block
                            ]
                        ]

Import exposing Properties

Hi, I've just been going through your README tutorials and noticed that it looks like the Properties import needs an exposing (...)

import Html.Animation.Properties exposing (..)

Love this library, by the way!

transformOrigin does not seem to work

Hey @mdgriffith,

Thanks again for this awesome package! I've tried about 4 different approaches to Css in Elm and this package is by far the best for animation with Elm, it actually saved me a lot of time utilizing the Animation.Messenger switching model types while animating.

transformOrigin seems to have no effect either with Animation.to or Animation.set
for example:
[ Animation.set [ Animation.transformOrigin (percent 50) (percent 0) (percent 0) ] will output no transform-origin property in the Html
the next lines are either rotate3d or translate3d that perform the transition from the default origin.

Hope you have time to fix, i'll take a look at the code later too.

Thanks

Rotate does not allow user to specify origin

The rotate transform for SVG takes two optional arguments that describe the point about which the element is to be rotated. Because the library does not expose these two arguments, the default of (0, 0) is always used. If I want to rotate an element about its center, I have to provide a transform value to compensate the rotation.

IMHO the ideal interface would look something like this:

rotate : Angle -> Maybe (Float, Float) -> Property

Animation.isRunning not exposed

In my view function I need to know if an animation is running to show appropriate elements accordingly. I noticed the function Animation.isRunning and I'm wondering if there is a reason why it's not exposed or if I'm using the wrong approach. Thank you.

Animation.set does not work

Tried it for Translate3d and got a whole lot of NaN values. I suspect that in Core.elm, some conflicts arise through division by zero because easing time is effectively set to zero for Animation.set.

Ex. Core.elm, Line 666 and Core.elm, Line 565

mouseDelta' =
  [ Translate3d dx dy 0 Px ]

( annotations', fx ) =
  UI.animate |> UI.set mouseDelta' |> onAnnotation id model.annotations

Moving an SVG

Hi,
great project, but I need help moving an SVG.

I created a "minimal example" (see below) that shows my attempt to move a svg triangle onClick using the Property "D".

Whilst the color change works (to show something is happening), the svg does not move. I'd expect it to move relatively by (-50, -50) units.

What am i doing wrong?
Thanks!

import Time exposing (second)
import Html.App
import Html exposing (div, Html)
import Html.Attributes as Attr
import Html.Events exposing (..)
import Svg exposing (..)
import Svg.Attributes exposing (..)
import AnimationFrame
import Style
import Style.Properties exposing (..)
import Color exposing (rgb)


type alias Model =
    { style : Style.Animation  }


type Action
    = Move
    | Animate Float


palette =
    { orange = rgb 244 156 59,
      red = rgb 127 0 0 }


logo =
    [ Points
            <| alignStartingPoint
                [ ( 150, 139.2)
                , ( 150, 239.05 )
                , ( 85.2, 197.15 )
                ]
      , Fill palette.orange
      , D [ ]
    ]


update : Action -> Model -> ( Model, Cmd Action )
update action model =
    case action of

        Move ->
            ( { model 
                | style = 
                    Style.animate
                        |> Style.to [ D [Style.Properties.Move -50 -50], Style.Properties.Fill palette.red ]
                        |> Style.on model.style
              }
            , Cmd.none
            )

        Animate time ->
            ( { model
                | style = Style.tick time model.style
              }
            , Cmd.none
            )


view : Model -> Html Action
view model =
    div
        [ onClick Move
        , Attr.style [ ( "margin", "0px auto" ), ( "width", "300px" ), ( "height", "300px" ), ("cursor", "pointer") ]
        ]
        [ svg
            [ version "1.1"
            , x "0"
            , y "0"
            , viewBox "0 0 300 300" 
            ]
            [ polygon (Style.renderAttr model.style) [] ]
        ]


subscriptions : Model -> Sub Action
subscriptions model =
    AnimationFrame.times Animate


init : ( Model, Cmd Action )
init =
    ( { style = Style.init logo }
    , Cmd.none
    )


main =
    Html.App.program
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }

Not setting animation speed results in broken animations

I had this code:

Animation.interrupt
                [ Animation.loop
                    [ Animation.to
                        [ Animation.rotate (Animation.turn 1) ]
                    , Animation.set [ Animation.rotate <| Animation.turn 0 ]
                    ]
                ]
                model.style

For a little spinner. The above results in one correct animation, and afterwards animations
spinner only abruptly resets itself to 0 in jumps.

Using this:

  Animation.interrupt
                [ Animation.loop
                    [ Animation.toWith (Animation.speed { perSecond = 1 })
                        [ Animation.rotate (Animation.turn 1) ]
                    , Animation.set [ Animation.rotate <| Animation.turn 0 ]
                    ]
                ]
                model.style

(Note we set animation speed)
fixes the problem.

Infinite Loop

Version 3.5.2

I created an animation with this easing:

controlBarHideEasing =
Animation.easing
{ duration = 1.2e-1 * second
, ease = Ease.inBack
}

The animation is to change from "left = -6 px" to "left = 24 px". The animation completes succesfully, but Animation events continue to Tick in an infinite loop after this.

Interestingly, if I make the animation smaller, say from -6 to -8, it completes ok.

I tried varying the duration, but no joy.

I replaced the easing function with: Ease.inOut Ease.inBack Ease.outQuad, which gives me more or less the same effect and it does not infinite loop.

I suspect there is some kind of rounding error in the code relating to the Ease.inBack function, it appears to never manage to reach 24px, but gets stuck at 23.999...?

To test this hypothesis, I also dumped out the model here it is:

controlBarStyle = Animation { steps = [Step], style = [Property "left" { position = 23.999999999999993, velocity = 0, target = 24, unit = "px", interpolation = Spring { stiffness = 170, damping = 26 }, interpolationOverride = Just (Easing { progress = 1, duration = 120, ease = , start = -6 }) }], timing = { current = 1486483235957, dt = 17 }, running = True, interruption = [] } }

Enable parallel playing of steps on the same animation

This makes it easier to re-use and combine existing step specifications. Imagine a flicker animation and a wiggle animation, playing independently (maybe also looping).

I'm not sure if interrupt is the right constructor for this as its description says

Interrupt any running animations with the following animation.

Maybe a new function like Animation.parallel, Animation.also or Animation.and might work?

Uncaught Error: Equality error: general function equality is undecidable, and therefore, unsupported

Hi again !

I ran into an issue using elm-style-animation. I'm getting this error (sporadically) :

Uncaught Error: Equality error: general function equality is undecidable, and therefore, unsupported

My model is a List TreeNode with

type alias TreeNode = {
    ...
    style : Style.Animation
}

I never test for equality (== or /=) myself on these records, do I'm not sure if I'm misusing the lib, or if it's an actual bug on your side. Plus I'm too much of an Elm noob to say right now.

Any idea ?

translate3d not working properly

Hi!
I've started using your awesome library to add some animations in a project I'm working on, but I'm having some issues trying to replicate this css animation:

@keyframes fadeInDown
  from
    opacity: 0
    transform: translate3d(0, -100%, 0)

  to
    opacity: 1
    transform: none


.fadeInDown
  animation-name: fadeInDown
  animation-duration: 300ms
  animation-fill-mode: both

This is my animation initial model:

initialModel =
  { ...
   , animationModel =
        { pageFormStyle =
            Animation.style
                [ Animation.translate3d (Animation.percent 0) (Animation.percent -100) (Animation.percent 0)
                , Animation.opacity 0
                ]
        }
    }

And here is the update function:

ShowCreatePageForm show ->
            let
                pageFormStyle =
                    case show of
                        Hide ->
                            Animation.interrupt
                                [ Animation.to
                                    [ Animation.translate3d (Animation.percent 0) (Animation.percent -100) (Animation.percent 0)
                                    , Animation.opacity 0
                                    ]
                                ]
                                model.animationModel.pageFormStyle

                        Show ->
                            Animation.interrupt
                                [ Animation.to
                                    [ Animation.exactly "transform" "none"
                                    , Animation.opacity 1
                                    ]
                                ]
                                model.animationModel.pageFormStyle
...

The problem is that the initial translate3d is not being applied, so a white space is shown as it's only applying the opacity: 0 style:

image

When the + Add new link is clicked to display the form it applies correctly the opacity only, showing it:

image

Clicking in the Cancel button will try to fade and slide up the form, but it only changes the opacity leaving the white space again.
Am I doing anything wrong? Thanks in advance :)

SVG height and width attributes

I'm animating SVG rect elements to show fluid levels decreasing. rect uses height and width attributes. Those aren't animatable via the API. I realize I could use points instead of rect, but these attributes might be broadly useful. (Alternately, perhaps a way to set custom SVG attributes, though the case statement in the code suggests that isn't straightforward.)

Interestingly, you can use the HTML height attribute, which results in an element like this:

<rect style="height: 0px;" y="90" fill="#d3d7cf" x="0" width="30"></rect>

That actually works in both Chrome and Safari, but not in Firefox.

Using `transform` property in `toWith`

Is there a way within this library to use something like transform rotate(80deg)? It's an animatable property, but I can't seem to get it to work. It appears that exactly is only for use with Animation.set, not gradual animations like toWith.

I'm trying to move a clock hand (using the three-argument version of rotate). I can do it with a polygon or path, but I was hoping to take advantage of defs and marker to make an arrowhead that rotates nicely along with the line.

screen shot 2016-09-25 at 4 53 24 pm

Difference in behavior depending on previous animation

TL;DR: An animation that flashes two different colors works only if a different animation precedes it. I suspect I'm doing something wrong, but it might be a bug.


I have an animation of an IV drip. The drip has two different appearances, depending on the speed the user types in. If the speed is slow, the drops look like this:

slow

(The animation is started or changed when focus leaves the text field.)

If the speed is fast, I show a bar that varies between two shades of grey to give a (crude) flowing appearance:

fast

However, that only happens if you switch from the slow animation to the fast one (by first typing something like "2" in the text field, leaving it, going back, then changing the value to "20").

  • high-speed changed to a different high speed still shows the solid bar.
  • fast->slow->fast shows the pulsing bar on the second fast.
  • Indeed, once there's been a slow, any future fast speed will pulse.

The source can be found here: https://github.com/marick/eecrit/blob/looping-oddity/web/elm/IV/Apparatus/Droplet.elm You can try the animation yourself at https://new.critter4us.com/iv (though I'm changing this frequently).

Both animations are started by this:

changeDropRate dropsPerSecond animation =
  let
    loop = Animation.loop (animationSteps dropsPerSecond)
  in
    Animation.interrupt [loop] animation

The steady stream is this:

steadyStream = 
  [ Animation.toWith (easing fallingTime) View.streamState1
  , Animation.toWith (easing fallingTime) View.streamState2
  ]

The "stream states" are from https://github.com/marick/eecrit/blob/looping-oddity/web/elm/IV/Apparatus/DropletView.elm

streamState1 =
  [ Animation.points flowInChamber
  , Animation.fill Palette.aluminum
  ]    

streamState2 =
  [ Animation.points flowInChamber
  , Animation.fill Palette.shiftedAluminum
  ]    

For what it's worth, the falling drop is done like this:

    [ Animation.set View.missingDrop
    , Animation.toWith (easing hangingTime) View.hangingDrop
    , Animation.toWith (easing fallingTime) View.fallenDrop
    ]

I'm using 3.2.0, but it seems the same issue happens on 3.0 and 3.1.

Behavior is the same on Chrome and Safari.

Animation.Messenger missing sends

I only see one Animation.Messenger.send only triggered once, instead of once per animation.

Steps

  • I have a list of 3 items, each with an Animation.Messenger.State
  • I call Animation.interrupt to start the animation on each item, with an Animation.Messenger.send to notify me when an animation is done.
  • I use Animation.Messenger.update for updates on each item.
  • I only see Animation.Messenger.send only triggered once, instead of once per item.

The use case is that I want to remove the item from a list when the animation is done.

I'm not sure if I'm using the library incorrectly, here is a gist of the problem:
https://gist.github.com/trotha01/0daa217c07bf05d859c8dcfe88229009

If you run the gist, we see that "start" is logged to the console 3 times, but "done" is only logged once.

Any help is appreciated, thank you!

text-shadow values don't match css syntax

css syntax for text-shadow: h-shadow v-shadow blur-radius color|none|initial|inherit;

textShadow : Shadow -> Animation.Model.Property
textShadow shade =
    let
        { red, green, blue, alpha } =
            Color.toRgb shade.color
    in
        ShadowProperty
            "text-shadow"
            False
            { offsetX = initMotion shade.offsetX "px"
            , offsetY = initMotion shade.offsetY "px"
            , size = initMotion shade.size "px"
            , blur = initMotion shade.blur "px"
            , red = initMotion (toFloat red) "px"
            , green = initMotion (toFloat green) "px"
            , blue = initMotion (toFloat blue) "px"
            , alpha = initMotion alpha "px"
            }

Animating text-shadow with large blur results in animation lag on mobile

I set up the animation like this:

                [ Animation.opacity 0
                , Animation.color Color.darkRed
                , Animation.textShadow
                  { offsetX = 5
                  , offsetY = 0
                  , size = 1
                  , blur = 60
                  , color = Color.rgba 160 90 90 0.7
                  }
                ]

And depending on the blur that I animate to, there will be more or less lag when visiting on mobile device.

For instance, laggier:

Animation.to
                            [ Animation.opacity 1.0
                            , Animation.color Color.red
                              , Animation.textShadow
                                 { offsetX = 0
                                 , offsetY = 1
                                 , size = 1
                                 , blur = 70
                                 , color = Color.rgba 223 87 96 0.9
                                 }

                            ]

Less laggy:

Animation.to
                            [ Animation.opacity 1.0
                            , Animation.color Color.red
                              , Animation.textShadow
                                 { offsetX = 0
                                 , offsetY = 1
                                 , size = 1
                                 , blur = 1
                                 , color = Color.rgba 223 87 96 0.9
                                 }

                            ]

Issue on importing

When I do imports, I like to be explicit about exposing types and functions. When I try and import specific types into my module I get the following error:

-- NAMING ERROR --------------------------------------- ././Components/Movie.elm

Module `Style.Properties` does not expose `Width`

8| import Style.Properties exposing (Width)
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

But when I type Import Style.Properties exposing(..) it works just fine. This is confusing because
I can also use Style.Properties.Width and that compiles. There is no documentation on this nor are the specific imports in any of the examples

Problem Cmd.mapping from child module

I'm an Elm newbie so perhaps I'm doing something wrong, but I think there's a problem.

I am doing animations in Main and in my ZombificationStatus (don't ask!) child component. I was successfully animating in both until I needed to use Animation.Messenger.send in Main. I made the changes you specify in the documentation:

In both modules, I
import Animation
import Animation.Messenger

and my models have something like this:
slidingOutStyle : Animation.Messenger.State Msg

The problem I am having is mapping the messages from my child to parent. If I don't map, I (understandbly) get:

-- TYPE MISMATCH -------------------------------------------------- src/Main.elm
The right side of (::) is causing a type mismatch.
677|                                         model.slidingOutStyle :: pageStyles)
                                                                                          ^^^^^^^^^^
(::) is expecting the right side to be a:
    List (Animation.Messenger.State Main.Msg)
But the right side is:
    List (Animation.Messenger.State ZombificationStatus.Msg)

--

So I try to map it:

mapToMain : Animation.Messenger.State Msg -> Animation.Messenger.State Msg
mapToMain thing =
    case thing of
        Animation.Messenger.State zombificationMsg ->
            Animation.Messenger.State (Cmd.map ZombificationStatus zombificationMsg)

and I get this compiler error:

-- NAMING ERROR --------------------------------------------------- src/Main.elm

Cannot find pattern `Animation.Messenger.State`.

681|         Animation.Messenger.State zombificationMsg ->
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
No module called `Animation.Messenger` has been imported.

-- NAMING ERROR --------------------------------------------------- src/Main.elm

Cannot find variable `Animation.Messenger.State`.

682|             Animation.Messenger.State (Cmd.map ZombificationStatusPage zombificationMsg)
                            ^^^^^^^^^^^^^^^
`Animation.Messenger` does not expose `State`.

Am I doing something wrong, or is there a problem here?

(perhaps this? elm/error-message-catalog#215 )

Thanks!

Floating point rounding issue

I was working on an animation which consisted of two steps, and noticed that the second step never got executed. It's probably easier to give a minimal example to explain:

module Main exposing (..)

import Animation exposing (..)
import Ease
import Html exposing (..)
import Html.Attributes
import Html.Events


main : Program Never Model Msg
main =
    program
        { init = init
        , update = update
        , subscriptions = subscriptions
        , view = view
        }


type alias Model =
    { style : Animation.State
    }


type Msg
    = Animate Animation.Msg
    | StartAnimation


subscriptions : Model -> Sub Msg
subscriptions model =
    Animation.subscription Animate [ model.style ]


init : ( Model, Cmd Msg )
init =
    ( { style =
            Animation.style
                [ Animation.opacity 1.0 ]
      }
    , Cmd.none
    )


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Animate animMsg ->
            ( { model | style = Animation.update animMsg model.style }
            , Cmd.none
            )

        StartAnimation ->
            ( { model
                | style =
                    Animation.interrupt
                        [ Animation.toWith
                            (Animation.easing
                                { duration = 600
                                , ease = Ease.outCubic
                                }
                            )
                            [ Animation.opacity 0.3 ]
                        , Animation.toWith
                            (Animation.easing
                                { duration = 600
                                , ease = Ease.outCubic
                                }
                            )
                            [ Animation.opacity 1.0 ]
                        ]
                        model.style
              }
            , Cmd.none
            )


view : Model -> Html Msg
view model =
    div []
        [ button [ Html.Events.onClick StartAnimation ] [ text <| "Start animation" ]
        , div
            (Animation.render model.style
                ++ [ Html.Attributes.style
                        [ ( "width", "100px" )
                        , ( "height", "100px" )
                        , ( "background-color", "blue" )
                        ]
                   ]
            )
            []
        ]

It's supposed to go from opacity 1 -> opacity 0.3 -> opacity 1, but it remains on opacity 0.3.

I think the error is in this code: https://github.com/mdgriffith/elm-style-animation/blob/master/src/Animation/Model.elm#L1616-L1617

I made a local copy and changed that to

newPos = (toFloat (truncate (((eased * duration) + start) * 1000))) / 1000

Then the animation does run to the end, but I'm not sure this is the best solution

How to animate with auto height ?

Hello,

I'm evaluating this library and I am new to Elm in general... apologies in advance if I ask a silly question !

Is there a way to animate an element without knowing its target height ? Stuff like a title pane that can be collapsed/expanded and contains arbitrary HTML.

I'd have done this like :

expanded : { height: auto } // or height : 100%
collapsed: { height: 0 }

But the API doesn't allow me to do this. Any idea ?

Thanks !

Style.repeat with Style.delay jerkiness

First of all, thanks for a great library!
I'm having some issues with my repeated animations that has delays. Not sure if this is even supported...

  Style.repeat 4
    |> Style.spring { stiffness =  300, damping = 18 }
    |> Style.to [ Left 150 Px , Opacity 1 ]
    |> Style.andThen
    |> Style.delay (0.5 * Time.second)
    |> Style.to [ Left 0 Px , Opacity 0.3 ]
    |> Style.on model.style

Here's how it looks:
jerkiness

Jerkiness also seem to sync with my delay (0.5sec).

Any ideas?

Full source

Properties not being animated after using Animation.exactly

I've noticed that if I use Animation.exactly to set some properties, those properties aren't animated/updated the next time they should be.

Animation.exactly and Animation.opacity (which, conveniently, happen to be defined next to each other) have the same return type (Animation.Model.Property), so I figured I'd be able to get away with using exactly throughout.

Here are the two variants of the piece of code in question:

-- works as expected
[ Animation.set
                    [ Animation.opacity 1
                    , Animation.scale 1.0
                    , Animation.exactly "z-index" "2"
                    ]
                ]
-- does not work as expected
-- opacity and scale are never updated 
[ Animation.set
                    [ Animation.exactly "opacity" "1"
                    , Animation.exactly "scale" "1.0"
                    , Animation.exactly "z-index" "2"
                    ]
                ]

Here's the relevant version information from my elm-package.json:

"dependencies": {
    "mdgriffith/elm-style-animation": "3.5.5 <= v < 4.0.0"
},
"elm-version": "0.18.0 <= v < 0.19.0"

Please let me know if there's any additional information I can provide.

P.S. Aside from this issue, the library has been a joy to work with! 😸

Length Unit mixing fails

If you try to do the following:

Animation.style [ Animation.top (percent 100) ]
    |> Animation.interrupt  [ Animation.to [ Animation.top (px -200) ] ]

Note the (px -200)

It actually goes to (percent -200)

Version 4.0 Features and Bugfixes

  • Issue warning if Animation.exact is being used not in Animation.set.
  • Animate along an svg path
  • Replace current SVG path API with elm-path
  • auto "draw" a path
  • Property animation independence (#38) ...vive la resistance!
  • transformOrigin only accepts px
  • rotate needs an alternative that specifies origin: rotateAround : Angle -> Point -> Prop
  • Use public facing type aliases in all public functions (#40)
  • A visual guide to using elm-style-animation
  • Some way to render raw values

Animating 2 widgets

Hello!

I have a question about the best way to handle two simple, but very different animations in single module. I have two animation styles defined in my model like this:

, styleInfo =
      UI.init
        [ Top -10.0 Px 
        , Opacity 0.5
        ]
  , styleMeter =
      UI.init
        [ Width 450.0 Px 
        ]

The styleInfo animates the position of an information drawer that slides up from the bottom. The styleMeter animates the width of a scale meter.

I have some actions that update the animations like this:

  -- The animation actions for the info drawer  
  ShowInfo ->
      let
        model' =
          { model 
              | infoBoxIsOpen = True
          }
      in
        UI.animate
          |> UI.spring UI.wobbly
          |> UI.props
              [ Top (UI.to -300) Px
              , Opacity (UI.to 1)
              ]
          |> onMenu model'

    HideInfo ->
      let
        model' =
          { model 
              | infoBoxIsOpen = False
          }
      in
      UI.animate
        |> UI.spring UI.wobbly
        |> UI.props
            [ Top (UI.to -10) Px
            , Opacity (UI.to 0.5)
            ]
        |> onMenu model'

  -- The animation to scale the width of the meter
 UpdateMeter level ->
      let
        model' =
          { model 
             | storyLevel = level
             , storyChapter = currentStoryChapter level model.totalStoryChapters
          }
      in
        UI.animate
          |> UI.spring UI.wobbly
          |> UI.props
              [ Width (UI.to (toFloat (meterWidth model'))) Px
              ]
          |> onMeter model'

Then I have helper functions to update these two different kinds of animations.

onMenu =
  UI.forwardTo Animate .styleInfo (\w styleInfo -> { w | styleInfo = styleInfo }) 

onMeter =
  UI.forwardTo Animate .styleMeter (\w styleMeter -> { w | styleMeter = styleMeter }) 

I've hooked all this up to my UI, and, when I test them individually, they work just fine (actually, they look really amazing, thanks!!).
But, of course, I can only run one of these at a time in the Animate action

Animate action ->
  onMenu model action

  -- or
  -- onMeter model action
  -- ... but not both

Could you suggest a solution as to how I could get both these animations to work at the same time?
I'm pretty sure the answer lies somewhere in your Example #3, but it's a little too advanced for me and I haven't yet been able to work out how to apply it my current problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.