{-| Effects represent modifications applied to frames of the 'Animation'. Effects can (and usually do) depend on time. One or more effects can be applied over the entire duration of animation, or modified to affect only a specific portion at the beginning \/ middle \/ end of the animation. -} module Reanimate.Effect ( -- * Primitive Effects Effect , fadeInE , fadeOutE , fadeLineInE , fadeLineOutE , fillInE , drawInE , drawOutE , translateE , scaleE , constE -- * Modifying Effects , overBeginning , overEnding , overInterval , reverseE , delayE , aroundCenterE -- * Applying Effects to Animations , applyE ) where import Graphics.SvgTree (Tree) import Reanimate.Animation import Reanimate.Svg -- | An Effect represents a modification of a SVG 'Tree' that can vary with time. type Effect = Duration -- ^ Duration of the effect (in seconds) -> Time -- ^ Time elapsed from when the effect started (in seconds) -> Tree -- ^ Image to be modified -> Tree -- ^ Image after modification -- | Modify the effect so that it only applies to the initial part of the animation. overBeginning :: Duration -- ^ Duration of the initial segment of the animation over which the Effect should be applied -> Effect -- ^ The Effect to modify -> Effect -- ^ Effect which will only affect the initial segment of the animation overBeginning :: Duration -> Effect -> Effect overBeginning Duration maxT Effect effect Duration _d Duration t = if Duration t Duration -> Duration -> Bool forall a. Ord a => a -> a -> Bool < Duration maxT then Effect effect Duration maxT Duration t else Tree -> Tree forall a. a -> a id -- | Modify the effect so that it only applies to the ending part of the animation. overEnding :: Duration -- ^ Duration of the ending segment of the animation over which the Effect should be applied -> Effect -- ^ The Effect to modify -> Effect -- ^ Effect which will only affect the ending segment of the animation overEnding :: Duration -> Effect -> Effect overEnding Duration minT Effect effect Duration d Duration t = if Duration t Duration -> Duration -> Bool forall a. Ord a => a -> a -> Bool >= Duration blankDur then Effect effect Duration minT (Duration tDuration -> Duration -> Duration forall a. Num a => a -> a -> a -Duration blankDur) else Tree -> Tree forall a. a -> a id where blankDur :: Duration blankDur = Duration dDuration -> Duration -> Duration forall a. Num a => a -> a -> a -Duration minT -- | Modify the effect so that it only applies within given interval of animation's running time. overInterval :: Time -- ^ time after start of animation when the effect should start -> Time -- ^ time after start of the animation when the effect should finish -> Effect -- ^ The Effect to modify -> Effect -- ^ Effect which will only affect the specified interval within the animation overInterval :: Duration -> Duration -> Effect -> Effect overInterval Duration start Duration end Effect effect Duration _d Duration t = if Duration start Duration -> Duration -> Bool forall a. Ord a => a -> a -> Bool <= Duration t Bool -> Bool -> Bool && Duration t Duration -> Duration -> Bool forall a. Ord a => a -> a -> Bool <= Duration end then Effect effect Duration dur ((Duration t Duration -> Duration -> Duration forall a. Num a => a -> a -> a - Duration start) Duration -> Duration -> Duration forall a. Fractional a => a -> a -> a / Duration dur) else Tree -> Tree forall a. a -> a id where dur :: Duration dur = Duration end Duration -> Duration -> Duration forall a. Num a => a -> a -> a - Duration start -- | @reverseE effect@ starts where the @effect@ ends and vice versa. reverseE :: Effect -> Effect reverseE :: Effect -> Effect reverseE Effect fn Duration d Duration t = Effect fn Duration d (Duration dDuration -> Duration -> Duration forall a. Num a => a -> a -> a -Duration t) -- | Delay the effect so that it only starts after specified duration and then runs till the end of animation. delayE :: Duration -> Effect -> Effect delayE :: Duration -> Effect -> Effect delayE Duration delayT Effect fn Duration d = Duration -> Effect -> Effect overEnding (Duration dDuration -> Duration -> Duration forall a. Num a => a -> a -> a -Duration delayT) Effect fn Duration d -- | Modify the animation by applying the effect. If desired, you can apply multiple effects to single animation by calling this function multiple times. applyE :: Effect -> Animation -> Animation applyE :: Effect -> Animation -> Animation applyE Effect fn Animation ani = let d :: Duration d = Animation -> Duration duration Animation ani in Duration -> (Duration -> Tree) -> Animation mkAnimation Duration d ((Duration -> Tree) -> Animation) -> (Duration -> Tree) -> Animation forall a b. (a -> b) -> a -> b $ \Duration t -> Effect fn Duration d (Duration dDuration -> Duration -> Duration forall a. Num a => a -> a -> a *Duration t) (Tree -> Tree) -> Tree -> Tree forall a b. (a -> b) -> a -> b $ Duration -> Animation -> Tree frameAt (Duration dDuration -> Duration -> Duration forall a. Num a => a -> a -> a *Duration t) Animation ani -- | Build an effect from an image-modifying function. This effect does not change as time passes. constE :: (Tree -> Tree) -> Effect constE :: (Tree -> Tree) -> Effect constE Tree -> Tree fn Duration _d Duration _t = Tree -> Tree fn -- | Change image opacity from 0 to 1. fadeInE :: Effect fadeInE :: Effect fadeInE Duration d Duration t = Duration -> Tree -> Tree withGroupOpacity (Duration tDuration -> Duration -> Duration forall a. Fractional a => a -> a -> a /Duration d) -- | Change image opacity from 1 to 0. Reverse of 'fadeInE'. fadeOutE :: Effect fadeOutE :: Effect fadeOutE = Effect -> Effect reverseE Effect fadeInE -- | Change stroke width from 0 to given value. fadeLineInE :: Double -> Effect fadeLineInE :: Duration -> Effect fadeLineInE Duration w Duration d Duration t = Duration -> Tree -> Tree withStrokeWidth (Duration wDuration -> Duration -> Duration forall a. Num a => a -> a -> a *(Duration tDuration -> Duration -> Duration forall a. Fractional a => a -> a -> a /Duration d)) -- | Change stroke width from given value to 0. Reverse of 'fadeLineInE'. fadeLineOutE :: Double -> Effect fadeLineOutE :: Duration -> Effect fadeLineOutE = Effect -> Effect reverseE (Effect -> Effect) -> (Duration -> Effect) -> Duration -> Effect forall b c a. (b -> c) -> (a -> b) -> a -> c . Duration -> Effect fadeLineInE -- | Effect of progressively drawing the image. Note that this will only affect primitive shapes (see 'pathify'). drawInE :: Effect drawInE :: Effect drawInE Duration d Duration t = Duration -> Tree -> Tree withFillOpacity Duration 0 (Tree -> Tree) -> (Tree -> Tree) -> Tree -> Tree forall b c a. (b -> c) -> (a -> b) -> a -> c . Duration -> Tree -> Tree partialSvg (Duration tDuration -> Duration -> Duration forall a. Fractional a => a -> a -> a /Duration d) (Tree -> Tree) -> (Tree -> Tree) -> Tree -> Tree forall b c a. (b -> c) -> (a -> b) -> a -> c . Tree -> Tree pathify -- | Reverse of 'drawInE'. drawOutE :: Effect drawOutE :: Effect drawOutE = Effect -> Effect reverseE Effect drawInE -- | Change fill opacity from 0 to 1. fillInE :: Effect fillInE :: Effect fillInE Duration d Duration t = Duration -> Tree -> Tree withFillOpacity Duration f where f :: Duration f = Duration tDuration -> Duration -> Duration forall a. Fractional a => a -> a -> a /Duration d -- | Change scale from 1 to given value. scaleE :: Double -> Effect scaleE :: Duration -> Effect scaleE Duration target Duration d Duration t = Duration -> Tree -> Tree scale (Duration 1 Duration -> Duration -> Duration forall a. Num a => a -> a -> a + (Duration targetDuration -> Duration -> Duration forall a. Num a => a -> a -> a -Duration 1) Duration -> Duration -> Duration forall a. Num a => a -> a -> a * Duration tDuration -> Duration -> Duration forall a. Fractional a => a -> a -> a /Duration d) -- | Move the image from its current position to the target x y coordinates. translateE :: Double -> Double -> Effect translateE :: Duration -> Duration -> Effect translateE Duration x Duration y Duration d Duration t = Effect translate (Duration x Duration -> Duration -> Duration forall a. Num a => a -> a -> a * Duration tDuration -> Duration -> Duration forall a. Fractional a => a -> a -> a /Duration d) (Duration y Duration -> Duration -> Duration forall a. Num a => a -> a -> a * Duration tDuration -> Duration -> Duration forall a. Fractional a => a -> a -> a /Duration d) -- | Transform the effect so that the image passed to the effect's image-modifying -- function has coordinates (0, 0) shifted to the center of its bounding box. -- Also see 'aroundCenter'. aroundCenterE :: Effect -> Effect aroundCenterE :: Effect -> Effect aroundCenterE Effect e Duration d Duration t = (Tree -> Tree) -> Tree -> Tree aroundCenter (Effect e Duration d Duration t)