Hylograph.Transition.Tick
- Package
- purescript-hylograph-transitions
- Repository
- afcondon/purescript-hylograph-transitions
Tick-Driven Transitions
Primitives for animating transitions using simulation ticks rather than CSS. This is the simulation-aware analog to d3-transition.
Key insight: Force simulations already have a tick loop. We can use that same loop to drive enter/exit/update animations, giving us:
- Predictable, debuggable behavior
- No CSS timing coordination
- Pure PureScript interpolation
Usage:
import Hylograph.Transition.Tick as T
-- In your state
type State = { entering :: Map String Progress, exiting :: Array (Transitioning Node) }
-- In tick handler
onTick state = do
let { active: stillEntering } = T.tickProgressMap 0.025 state.entering
let { active: stillExiting } = T.tickTransitions 0.025 state.exiting
-- render with interpolated values
-- In render
radius = case enterProgress of
Just p -> T.lerp 20.0 5.0 (T.easeOut p)
Nothing -> 5.0
#Transitioning Source
type Transitioning a = { item :: a, progress :: Progress }An item in transition, carrying its state and progress
#tickProgressMap Source
tickProgressMap :: forall k. Ord k => TickDelta -> Map k Progress -> { active :: Map k Progress, completed :: Array k }Advance all progress values in a Map, partitioning into active and completed
let { active, completed } = tickProgressMap 0.025 enteringNodes
-- active: nodes still animating
-- completed: keys that just finished (for cleanup, callbacks, etc.)
#tickTransitions Source
tickTransitions :: forall a. TickDelta -> Array (Transitioning a) -> { active :: Array (Transitioning a), completed :: Array a }Advance all transitions, partitioning into active and completed
let { active, completed } = tickTransitions 0.025 exitingNodes
-- active: items still animating out
-- completed: items that finished (now safe to remove from DOM)
#startTransitions Source
startTransitions :: forall a. Array a -> Array (Transitioning a)Wrap items as transitions starting at progress 0.0
#startTransitionsFrom Source
startTransitionsFrom :: forall a. Progress -> Array a -> Array (Transitioning a)Wrap items as transitions starting at a specific progress
#lerpClamped Source
lerpClamped :: Number -> Number -> Progress -> NumberLinear interpolation with progress clamped to [0, 1]
#easeInQuad Source
easeInQuad :: EasingQuadratic ease in: t²
#easeOutQuad Source
easeOutQuad :: EasingQuadratic ease out: 1 - (1-t)²
#easeInOutQuad Source
easeInOutQuad :: EasingQuadratic ease in-out
#easeInCubic Source
easeInCubic :: EasingCubic ease in: t³
#easeOutCubic Source
easeOutCubic :: EasingCubic ease out: 1 - (1-t)³
#easeInOutCubic Source
easeInOutCubic :: EasingCubic ease in-out
#easeOutSin Source
easeOutSin :: EasingSinusoidal ease out: sin(t * π/2)
#easeInOutSin Source
easeInOutSin :: EasingSinusoidal ease in-out: -(cos(π * t) - 1) / 2
#easeOutExp Source
easeOutExp :: EasingExponential ease out: 1 - 2^(-10 * t)
#easeInOutExp Source
easeInOutExp :: EasingExponential ease in-out
#easeInCircle Source
easeInCircle :: EasingCircular ease in: 1 - sqrt(1 - t²)
#easeOutCircle Source
easeOutCircle :: EasingCircular ease out: sqrt(1 - (t - 1)²)
#easeInOutCircle Source
easeInOutCircle :: EasingCircular ease in-out
#easeInBack Source
easeInBack :: EasingBack ease in: overshoots then returns
#easeOutBack Source
easeOutBack :: EasingBack ease out: overshoots past target then settles
#easeInOutBack Source
easeInOutBack :: EasingBack ease in-out: overshoots on both ends
#easeInElastic Source
easeInElastic :: EasingElastic ease in: spring-like start
#easeOutElastic Source
easeOutElastic :: EasingElastic ease out: spring-like end (most common)
#easeInOutElastic Source
easeInOutElastic :: EasingElastic ease in-out: spring on both ends
#easeInBounce Source
easeInBounce :: EasingBounce ease in: reverse of bounce out
#easeOutBounce Source
easeOutBounce :: EasingBounce ease out: ball bouncing to rest
#easeInOutBounce Source
easeInOutBounce :: EasingBounce ease in-out: bounce on both ends
#withEasing Source
withEasing :: forall a. Easing -> (Progress -> a) -> Progress -> aApply easing to an interpolation function
-- Ease-out shrink from 20 to 5
radius = withEasing easeOut (lerp 20.0 5.0) progress
#ticksForDuration Source
ticksForDuration :: Int -> TickDeltaCalculate tick delta for a desired duration at assumed 60fps
ticksForDuration 1000 -- 0.0167 (1 second at 60fps)
ticksForDuration 500 -- 0.0333 (0.5 seconds)