Only render a transition in the cases where it doesn't sometimes break

This commit is contained in:
Matthew Griffith 2024-05-08 09:22:37 -04:00
parent f4fa423969
commit 2c79dd3963
4 changed files with 156 additions and 73 deletions

View File

@ -254,13 +254,21 @@ ms =
{-| -}
delay : Duration -> Animation -> Animation
delay dur (Animation now attrs) =
Animation (Time.rollbackBy dur now) attrs
delay dur (Animation { now, attrs, allowTransitions }) =
Animation
{ allowTransitions = allowTransitions
, now = Time.rollbackBy dur now
, attrs = attrs
}
{-| -}
type Animation
= Animation Time.Absolute (List Css.RenderedProp)
= Animation
{ now : Time.Absolute
, attrs : List Css.RenderedProp
, allowTransitions : Move.AllowTransitions
}
{-| -}
@ -345,8 +353,10 @@ keyframes steps =
}
in
Animation
(Timeline.getUpdatedAt timeline)
(Css.propsToRenderedProps timeline identity)
{ allowTransitions = Move.DisallowTransitions
, now = Timeline.getUpdatedAt timeline
, attrs = Css.propsToRenderedProps timeline identity
}
toOccurring : Time.Absolute -> Step -> ( Time.Absolute, Timeline.Occurring (List Attribute) )
@ -693,8 +703,10 @@ Anim.div
onTimeline : Timeline state -> (state -> List Attribute) -> Animation
onTimeline timeline toProps =
Animation
(Timeline.getUpdatedAt timeline)
(Css.propsToRenderedProps timeline toProps)
{ allowTransitions = Move.DisallowTransitions
, now = Timeline.getUpdatedAt timeline
, attrs = Css.propsToRenderedProps timeline toProps
}
{-| -}
@ -719,8 +731,10 @@ onTimelineWith timeline toPropsAndSteps =
|> List.map (addSequenceSteps 1 fullDuration steps)
in
Animation
(Timeline.getUpdatedAt timeline)
(Css.propsToRenderedProps timeline toProps)
{ allowTransitions = Move.DisallowTransitions
, now = Timeline.getUpdatedAt timeline
, attrs = Css.propsToRenderedProps timeline toProps
}
{-|
@ -770,15 +784,21 @@ transition transitionDuration props =
, interruption = []
, running = True
}
renderedProps =
Css.propsToRenderedProps timeline identity
in
Animation (Timeline.getUpdatedAt timeline)
(Css.propsToRenderedProps timeline identity)
Animation
{ now = Timeline.getUpdatedAt timeline
, allowTransitions = Move.AllowTransitions
, attrs = renderedProps
}
{-| -}
toCss : Animation -> Css
toCss (Animation now renderedProps) =
Css.toCss now renderedProps
toCss (Animation anim) =
Css.toCss anim
{-| -}
@ -787,10 +807,10 @@ div :
-> List (Html.Attribute msg)
-> List (Html msg)
-> Html msg
div (Animation now renderedProps) attrs children =
div (Animation anim) attrs children =
let
rendered =
Css.toCss now renderedProps
Css.toCss anim
in
Html.div
(List.map (\( key, val ) -> Attr.style key val) rendered.props ++ attrs)
@ -806,10 +826,10 @@ node :
-> List (Html.Attribute msg)
-> List (Html msg)
-> Html msg
node name (Animation now renderedProps) attrs children =
node name (Animation anim) attrs children =
let
rendered =
Css.toCss now renderedProps
Css.toCss anim
in
Html.node name
(List.map (\( key, val ) -> Attr.style key val) rendered.props ++ attrs)
@ -843,8 +863,10 @@ css timeline toPropsAndSteps =
|> List.map (addSequenceSteps 1 fullDuration steps)
in
Css.toCss
(Timeline.getUpdatedAt timeline)
(Css.propsToRenderedProps timeline toProps)
{ allowTransitions = Move.DisallowTransitions
, now = Timeline.getUpdatedAt timeline
, attrs = Css.propsToRenderedProps timeline toProps
}
{-| -}

View File

@ -3,6 +3,7 @@ module InternalAnim.Css exposing
, RenderedProp(..)
, match
, propsToRenderedProps
, renderedPropHasSequence
, toCss
)
@ -117,11 +118,16 @@ type alias Css =
}
toCss : Time.Absolute -> List RenderedProp -> Css
toCss now renderedProps =
toCss :
{ now : Time.Absolute
, attrs : List RenderedProp
, allowTransitions : Move.AllowTransitions
}
-> Css
toCss { allowTransitions, now, attrs } =
let
cssDetails =
props2Css now renderedProps emptyAnim
props2Css allowTransitions now attrs emptyAnim
in
{ hash = cssDetails.hash
, keyframes = cssDetails.keyframes
@ -410,14 +416,15 @@ addInitialProps props rendered =
new
props2Css : Time.Absolute -> List RenderedProp -> CssAnim -> CssAnim
props2Css now renderedProps anim =
props2Css : Move.AllowTransitions -> Time.Absolute -> List RenderedProp -> CssAnim -> CssAnim
props2Css allowTransitions now renderedProps anim =
case renderedProps of
[] ->
anim
(RenderedProp details) :: remain ->
props2Css now
props2Css allowTransitions
now
remain
(case details.sections of
[] ->
@ -440,6 +447,7 @@ props2Css now renderedProps anim =
_ ->
Move.cssForSections now
allowTransitions
(Units.inPixels details.state.position)
details.name
(\t one two ->
@ -456,7 +464,8 @@ props2Css now renderedProps anim =
)
(RenderedColorProp details) :: remain ->
props2Css now
props2Css allowTransitions
now
remain
(case details.sections of
[] ->
@ -471,6 +480,7 @@ props2Css now renderedProps anim =
_ ->
Move.cssForSections now
allowTransitions
details.color
details.name
(\t one two ->
@ -487,7 +497,8 @@ props2Css now renderedProps anim =
)
(VectorProp details) :: remain ->
props2Css now
props2Css allowTransitions
now
remain
(case details.sections of
[] ->
@ -502,6 +513,7 @@ props2Css now renderedProps anim =
_ ->
Move.cssForSections now
allowTransitions
(vectorStateToVector details.state)
details.name
(\t one two ->
@ -1147,6 +1159,34 @@ type RenderedProp
| VectorProp VectorDetails
renderedPropHasSequence : RenderedProp -> Bool
renderedPropHasSequence renderedProp =
case renderedProp of
RenderedProp details ->
case details.sections of
[] ->
False
_ ->
True
RenderedColorProp details ->
case details.sections of
[] ->
False
_ ->
True
VectorProp details ->
case details.sections of
[] ->
False
_ ->
True
type alias Vector =
{ x : Float
, y : Float

View File

@ -4,10 +4,11 @@ module InternalAnim.Move exposing
, lerpColor, lerpFloat, lerpVector
, Sequence(..)
, Step(..), stepWith
, sequences
, addSequence, cssForSections
, sequences, hasSequence
, addSequence, cssForSections, AllowTransitions(..)
, withTransition, withVelocities
, at
, denormalize
, move, toState
)
@ -22,14 +23,16 @@ module InternalAnim.Move exposing
@docs Sequence
@docs Step, stepWith
@docs sequences, goto
@docs sequences, goto, hasSequence
@docs addSequence, cssForSections
@docs addSequence, cssForSections, AllowTransitions
@docs withTransition, withVelocities
@docs at
@docs denormalize
-}
import Bezier
@ -41,6 +44,18 @@ import InternalAnim.Transition as Transition
import InternalAnim.Units as Units
{-| If this is a simple transition, then we can render it as a browser transition.
Otherwise, if it has sequences, then it needs to be rendered as a CSS animation.
Value animations don't care.
-}
hasSequence : Move value -> Bool
hasSequence (Pos _ _ seq) =
not (List.isEmpty seq)
{-| -}
type Move value
= Pos Transition.Transition value (List (Sequence value))
@ -103,10 +118,12 @@ We need to know:
Also, each `value` needs all information about how to get to the next `value`
which is the opposite of what elm-animator does.
-}
type
Sequence value
-- repeat, delay, duration
-}
type Sequence value
= Sequence Int Duration.Duration Duration.Duration (List (Step value))
@ -801,6 +818,11 @@ type alias CssAnim =
}
type AllowTransitions
= AllowTransitions
| DisallowTransitions
{-|
- For the first curve of the first step of the first sequence
@ -813,6 +835,7 @@ type alias CssAnim =
-}
cssForSections :
Time.Absolute
-> AllowTransitions
-> value
-> String
-> (Float -> value -> value -> String)
@ -821,38 +844,48 @@ cssForSections :
-> List (Sequence value)
-> CssAnim
-> CssAnim
cssForSections now startPos name lerp toString toHashString sections anim =
cssForSections now allowTransitions startPos name lerp toString toHashString sections anim =
case sections of
[] ->
anim
[ (Sequence 1 delay _ [ Step stepDur (Transition.Transition spline) v ]) as seq ] ->
-- NOTE, we're not using the above `dur` because it's the total duration of the sequence
-- and therefore equal to stepDur in this case
{ anim
| hash =
case anim.hash of
"" ->
hash now name seq toHashString
case allowTransitions of
AllowTransitions ->
-- NOTE, we're not using the above `dur` because it's the total duration of the sequence
-- and therefore equal to stepDur in this case
{ anim
| hash =
case anim.hash of
"" ->
hash now name seq toHashString
_ ->
anim.hash ++ hash now name seq toHashString
, transition =
case anim.transition of
"" ->
renderTransition name delay stepDur spline
_ ->
anim.hash ++ hash now name seq toHashString
, transition =
case anim.transition of
"" ->
renderTransition name delay stepDur spline
_ ->
renderTransition name delay stepDur spline ++ ", " ++ anim.transition
, props =
( name, toString v )
:: anim.props
}
_ ->
renderTransition name delay stepDur spline ++ ", " ++ anim.transition
, props =
( name, toString v )
:: anim.props
}
DisallowTransitions ->
toCssKeyframes
now
startPos
name
lerp
toString
toHashString
sections
anim
_ ->
-- -- most common situation
-- -- Renders the first step as a transition
-- -- and all subsequent steps as css keyframes
toCssKeyframes
now
startPos
@ -952,10 +985,10 @@ css now startPos name lerp toString toHashString seq =
{ hash = animationName
, transition = ""
, animation =
(durationStr ++ " ")
durationStr
-- we specify an easing function here because it we have to
-- , but it is overridden by the one in keyframes
++ "linear "
++ " linear "
++ delayStr
++ " "
++ n

View File

@ -346,13 +346,7 @@ keyframes interpolate startPercent endPercent transition =
-}
kf : Float -> String -> Bezier.Spline -> String
kf percent prop spline =
if percent == 0 then
String.fromInt (floor percent)
++ "% {animation-timing-function:"
++ Bezier.toCss spline
++ ";}"
else if percent == 100 then
if percent == 100 then
String.fromInt (floor percent)
++ "% {"
++ prop
@ -369,13 +363,7 @@ kf percent prop spline =
keyframeFromSpline : Float -> value -> (value -> String) -> Bezier.Spline -> String
keyframeFromSpline percent start toString spline =
if percent == 0 then
String.fromInt (floor percent)
++ "% {animation-timing-function:"
++ Bezier.toCss spline
++ ";}"
else if percent == 100 then
if percent == 100 then
String.fromInt (floor percent)
++ "% {"
++ toString start