Skip to content

Custom Color Property

Animate any color CSS property.

Module: Anim.Property.CustomColor

GPU Accelerated: No

Example

View Example

View Source Code
module Animation.Transition.BorderColor.Main exposing (main)

import Anim.Builder exposing (AnimBuilder)
import Anim.Engine.Transition as Transition
import Anim.Extra.Color as Color
import Anim.Property.CustomColor as CustomColor
import Browser
import Html exposing (Html, button, div, text)
import Html.Attributes exposing (class, style)
import Html.Events exposing (onClick)
import Motion.Easing as Easing exposing (Easing(..))



-- MAIN


main : Program () Model Msg
main =
    Browser.element
        { init = \_ -> init
        , view = view
        , update = update
        , subscriptions = always Sub.none
        }



-- MODEL


type alias Model =
    { animState : Transition.AnimState }


init : ( Model, Cmd Msg )
init =
    ( { animState =
            Transition.init
                [ CustomColor.init animGroup
                    CustomColor.BorderColor
                    (Color.rgb 99 102 241)
                ]
      }
    , Cmd.none
    )



-- ANIMATION


animGroup : String
animGroup =
    "borderAnim"


standardTiming : CustomColor.Builder { prop | withTiming : () } -> CustomColor.Builder { prop | withTiming : () }
standardTiming =
    CustomColor.duration 800
        >> CustomColor.easing CubicInOut


toRed : AnimBuilder { eng | withTiming : () } -> AnimBuilder { eng | withTiming : () }
toRed =
    CustomColor.begin CustomColor.BorderColor
        >> CustomColor.to (Color.rgb 239 68 68)
        >> standardTiming
        >> CustomColor.end


toBlue : AnimBuilder { eng | withTiming : () } -> AnimBuilder { eng | withTiming : () }
toBlue =
    CustomColor.begin CustomColor.BorderColor
        >> CustomColor.to (Color.rgb 59 130 246)
        >> standardTiming
        >> CustomColor.end



-- UPDATE


type Msg
    = TriggerRed
    | TriggerBlue


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        TriggerRed ->
            ( { model
                | animState =
                    Transition.animate model.animState <|
                        Transition.for animGroup
                            >> toRed
              }
            , Cmd.none
            )

        TriggerBlue ->
            ( { model
                | animState =
                    Transition.animate model.animState <|
                        Transition.for animGroup
                            >> toBlue
              }
            , Cmd.none
            )



-- VIEW


view : Model -> Html Msg
view model =
    div [ class "example-stage" ]
        [ div [ class "example-controls" ]
            [ button
                [ onClick TriggerRed
                , class "ui-action-button"
                , style "background-color" "#ef4444"
                ]
                [ text "Red Border" ]
            , button
                [ onClick TriggerBlue
                , class "ui-action-button"
                , style "background-color" "#3b82f6"
                ]
                [ text "Blue Border" ]
            ]
        , div
            [ style "width" "100%"
            , style "display" "flex"
            , style "align-items" "center"
            , style "justify-content" "center"
            , style "padding-top" "10px"
            ]
            [ div
                (Transition.attributes animGroup model.animState
                    ++ [ class "example-box"
                       , style "background-color" "#f8fafc"
                       , style "border" "4px solid #6366f1"
                       , style "border-radius" "8px"
                       ]
                )
                []
            ]
        ]
module Animation.Keyframe.BorderColor.Main exposing (main)

import Anim.Builder exposing (AnimBuilder)
import Anim.Engine.Keyframe as Keyframe
import Anim.Extra.Color as Color
import Anim.Property.CustomColor as CustomColor
import Browser
import Html exposing (Html, button, div, text)
import Html.Attributes exposing (class, style)
import Html.Events exposing (onClick)
import Motion.Easing as Easing exposing (Easing(..))



-- MAIN


main : Program () Model Msg
main =
    Browser.element
        { init = \_ -> init
        , view = view
        , update = update
        , subscriptions = always Sub.none
        }



-- MODEL


type alias Model =
    { animState : Keyframe.AnimState }


init : ( Model, Cmd Msg )
init =
    ( { animState =
            Keyframe.init <|
                [ CustomColor.init animGroup
                    CustomColor.BorderColor
                    (Color.rgb 99 102 241)
                ]
      }
    , Cmd.none
    )



-- ANIMATION


animGroup : String
animGroup =
    "borderAnim"


toRed : AnimBuilder { eng | withTiming : () } -> AnimBuilder { eng | withTiming : () }
toRed =
    CustomColor.begin CustomColor.BorderColor
        >> CustomColor.to (Color.rgb 239 68 68)
        >> CustomColor.duration 800
        >> CustomColor.easing CubicInOut
        >> CustomColor.end


toBlue : AnimBuilder { eng | withTiming : () } -> AnimBuilder { eng | withTiming : () }
toBlue =
    CustomColor.begin CustomColor.BorderColor
        >> CustomColor.to (Color.rgb 59 130 246)
        >> CustomColor.duration 800
        >> CustomColor.easing CubicInOut
        >> CustomColor.end



-- UPDATE


type Msg
    = TriggerRed
    | TriggerBlue


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        TriggerRed ->
            ( { model
                | animState =
                    Keyframe.animate model.animState <|
                        Keyframe.for animGroup
                            >> toRed
              }
            , Cmd.none
            )

        TriggerBlue ->
            ( { model
                | animState =
                    Keyframe.animate model.animState <|
                        Keyframe.for animGroup
                            >> toBlue
              }
            , Cmd.none
            )



-- VIEW


view : Model -> Html Msg
view model =
    div
        [ class "example-stage"
        , style "text-align" "center"
        ]
        [ Keyframe.styleNode model.animState
        , div [ class "example-controls" ]
            [ button
                [ onClick TriggerRed
                , class "ui-action-button"
                , style "background-color" "#ef4444"
                ]
                [ text "Red Border" ]
            , button
                [ onClick TriggerBlue
                , class "ui-action-button"
                , style "background-color" "#3b82f6"
                ]
                [ text "Blue Border" ]
            ]
        , div
            [ style "width" "100%"
            , style "display" "flex"
            , style "align-items" "center"
            , style "justify-content" "center"
            , style "padding-top" "10px"
            ]
            [ div
                (Keyframe.attributes animGroup model.animState
                    ++ [ class "example-box"
                       , style "background-color" "#f8fafc"
                       , style "border" "4px solid #6366f1"
                       , style "border-radius" "8px"
                       ]
                )
                []
            ]
        ]
module Animation.Sub.BorderColor.Main exposing (main)

import Anim.Builder exposing (AnimBuilder)
import Anim.Engine.Sub as Sub
import Anim.Extra.Color as Color
import Anim.Property.CustomColor as CustomColor
import Browser
import Html exposing (Html, button, div, text)
import Html.Attributes exposing (class, style)
import Html.Events exposing (onClick)
import Motion.Easing as Easing exposing (Easing(..))



-- MAIN


main : Program () Model Msg
main =
    Browser.element
        { init = \_ -> init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }



-- MODEL


type alias Model =
    { animState : Sub.AnimState }


init : ( Model, Cmd Msg )
init =
    ( { animState =
            Sub.init <|
                [ CustomColor.init animGroup
                    CustomColor.BorderColor
                    (Color.rgb 99 102 241)
                ]
      }
    , Cmd.none
    )



-- ANIMATION


animGroup : String
animGroup =
    "borderAnim"


standardTiming : CustomColor.Builder { prop | withTiming : () } -> CustomColor.Builder { prop | withTiming : () }
standardTiming =
    CustomColor.duration 800
        >> CustomColor.easing CubicInOut


toRed : AnimBuilder { eng | withTiming : () } -> AnimBuilder { eng | withTiming : () }
toRed =
    CustomColor.begin CustomColor.BorderColor
        >> CustomColor.to (Color.rgb 239 68 68)
        >> standardTiming
        >> CustomColor.end


toBlue : AnimBuilder { eng | withTiming : () } -> AnimBuilder { eng | withTiming : () }
toBlue =
    CustomColor.begin CustomColor.BorderColor
        >> CustomColor.to (Color.rgb 59 130 246)
        >> standardTiming
        >> CustomColor.end



-- UPDATE


type Msg
    = GotSubMsg Sub.AnimMsg
    | TriggerRed
    | TriggerBlue


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GotSubMsg subMsg ->
            let
                ( newAnimState, _ ) =
                    Sub.update subMsg model.animState
            in
            ( { model | animState = newAnimState }
            , Cmd.none
            )

        TriggerRed ->
            ( { model
                | animState =
                    Sub.animate model.animState <|
                        Sub.for animGroup
                            >> toRed
              }
            , Cmd.none
            )

        TriggerBlue ->
            ( { model
                | animState =
                    Sub.animate model.animState <|
                        Sub.for animGroup
                            >> toBlue
              }
            , Cmd.none
            )



-- SUBSCRIPTIONS


subscriptions : Model -> Sub.Sub Msg
subscriptions model =
    Sub.subscriptions GotSubMsg model.animState



-- VIEW


view : Model -> Html Msg
view model =
    div
        [ class "example-stage" ]
        [ div [ class "example-controls" ]
            [ button
                [ onClick TriggerRed
                , class "ui-action-button"
                , style "background-color" "#ef4444"
                ]
                [ text "Red Border" ]
            , button
                [ onClick TriggerBlue
                , class "ui-action-button"
                , style "background-color" "#3b82f6"
                ]
                [ text "Blue Border" ]
            ]
        , div
            [ style "width" "100%"
            , style "display" "flex"
            , style "align-items" "center"
            , style "justify-content" "center"
            , style "padding-top" "10px"
            ]
            [ div
                (Sub.attributes animGroup model.animState
                    ++ [ class "example-box"
                       , style "background-color" "#f8fafc"
                       , style "border" "4px solid #6366f1"
                       , style "border-radius" "8px"
                       ]
                )
                []
            ]
        ]
port module Animation.WAAPI.BorderColor.Main exposing (main)

import Anim.Builder exposing (AnimBuilder)
import Anim.Engine.WAAPI as WAAPI
import Anim.Extra.Color as Color
import Anim.Property.CustomColor as CustomColor
import Browser
import Html exposing (Html, button, div, text)
import Html.Attributes exposing (class, style)
import Html.Events exposing (onClick)
import Json.Encode as Encode
import Motion.Easing as Easing exposing (Easing(..))



-- PORTS


port motionCmd : Encode.Value -> Cmd msg


port motionMsg : (Encode.Value -> msg) -> Sub msg



-- MAIN


main : Program () Model Msg
main =
    Browser.element
        { init = \_ -> init
        , view = view
        , update = update
        , subscriptions = subscriptions
        }



-- MODEL


type alias Model =
    { animState : WAAPI.AnimState Msg }


init : ( Model, Cmd Msg )
init =
    ( { animState =
            WAAPI.init motionCmd motionMsg <|
                [ CustomColor.init animGroup
                    CustomColor.BorderColor
                    (Color.rgb 99 102 241)
                ]
      }
    , Cmd.none
    )



-- ANIMATION


animGroup : String
animGroup =
    "borderAnim"


standardTiming : CustomColor.Builder { prop | withTiming : () } -> CustomColor.Builder { prop | withTiming : () }
standardTiming =
    CustomColor.duration 800
        >> CustomColor.easing CubicInOut


toRed : AnimBuilder { eng | withTiming : () } -> AnimBuilder { eng | withTiming : () }
toRed =
    CustomColor.begin CustomColor.BorderColor
        >> CustomColor.to (Color.rgb 239 68 68)
        >> standardTiming
        >> CustomColor.end


toBlue : AnimBuilder { eng | withTiming : () } -> AnimBuilder { eng | withTiming : () }
toBlue =
    CustomColor.begin CustomColor.BorderColor
        >> CustomColor.to (Color.rgb 59 130 246)
        >> standardTiming
        >> CustomColor.end



-- UPDATE


type Msg
    = GotWaapiMsg WAAPI.AnimMsg
    | TriggerRed
    | TriggerBlue


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GotWaapiMsg waapiMsg ->
            let
                ( newAnimState, _ ) =
                    WAAPI.update waapiMsg model.animState
            in
            ( { model | animState = newAnimState }
            , Cmd.none
            )

        TriggerRed ->
            let
                ( newAnimState, cmd ) =
                    WAAPI.animate model.animState <|
                        WAAPI.for animGroup
                            >> toRed
            in
            ( { model | animState = newAnimState }
            , cmd
            )

        TriggerBlue ->
            let
                ( newAnimState, cmd ) =
                    WAAPI.animate model.animState <|
                        WAAPI.for animGroup
                            >> toBlue
            in
            ( { model | animState = newAnimState }
            , cmd
            )



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    WAAPI.subscriptions GotWaapiMsg model.animState



-- VIEW


view : Model -> Html Msg
view model =
    div
        [ class "example-stage"
        , style "text-align" "center"
        ]
        [ div [ class "example-controls" ]
            [ button
                [ onClick TriggerRed
                , class "ui-action-button"
                , style "background-color" "#ef4444"
                ]
                [ text "Red Border" ]
            , button
                [ onClick TriggerBlue
                , class "ui-action-button"
                , style "background-color" "#3b82f6"
                ]
                [ text "Blue Border" ]
            ]
        , div
            [ style "width" "100%"
            , style "display" "flex"
            , style "align-items" "center"
            , style "justify-content" "center"
            , style "padding-top" "10px"
            ]
            [ div
                (WAAPI.attributes animGroup model.animState
                    ++ [ class "example-box"
                       , style "background-color" "#f8fafc"
                       , style "border" "4px solid #6366f1"
                       , style "border-radius" "8px"
                       ]
                )
                []
            ]
        ]

Basic Usage

View Source Code
import Anim.Extra.Color as Color
import Anim.Property.CustomColor as CustomColor

borderColorAnimation : AnimBuilder eng -> AnimBuilder eng
borderColorAnimation =
    CustomColor.begin CustomColor.BorderColor            
        >> CustomColor.to (Color.rgb 255 0 0)
        >> CustomColor.end

See the Properties Overview page for the shared usage patterns.

API

Types

Type Description
Builder Alias for the Internal builder used to configure the animation
AnimGroupName Alias for the animation group name
ColorProperty Typed property names

Initialization

Function Signature Description
init AnimGroupName -> ColorProperty -> Color -> AnimBuilder eng -> AnimBuilder eng Set the initial color — takes group name, typed color property, and color

Build

Function Signature Description
for AnimGroupName -> ColorProperty -> AnimBuilder eng -> Builder eng Start building — takes group name and typed color property
build Builder eng -> AnimBuilder eng Finish building

Start Value

Function Signature Description
from Color -> Builder eng -> Builder eng Starting color

End Value

Function Signature Description
to Color -> Builder eng -> Builder eng Ending color

Timing

Function Signature Description
delay Int -> Builder { eng | withTiming : () } -> Builder { eng | withTiming : () } The delay in ms before the animation starts
duration Int -> Builder { eng | withTiming : () } -> Builder { eng | withTiming : () } The duration in ms that the animation lasts for
speed Float -> Builder { eng | withTiming : () } -> Builder { eng | withTiming : () } The rate of change per second

Easing

Function Signature Description
easing Easing -> Builder eng -> Builder eng Add natural motion

Spring

Function Signature Description
spring Spring -> Builder { eng | withSpring : () } -> Builder { eng | withSpring : () } Use spring physics instead of easing

Next Steps

Learn about animating with Discrete Properties.

Discrete Properties →