diff --git a/src/Reanimate.hs b/src/Reanimate.hs index 6b26946..93ce3c7 100644 --- a/src/Reanimate.hs +++ b/src/Reanimate.hs @@ -86,6 +86,7 @@ module Reanimate Effect, overBeginning, overEnding, + overInterval, reverseE, delayE, applyE, @@ -97,6 +98,7 @@ module Reanimate drawInE, drawOutE, fillInE, + scaleE, translateE, aroundCenterE, transitions, diff --git a/src/Reanimate/Effect.hs b/src/Reanimate/Effect.hs index 570efde..d12cb28 100644 --- a/src/Reanimate/Effect.hs +++ b/src/Reanimate/Effect.hs @@ -1,65 +1,130 @@ -module Reanimate.Effect where +{-| 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 -type Effect = Double -> Double -> Tree -> Tree +-- | 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 -overBeginning :: Double -> Effect -> Effect -overBeginning maxT fn = \_d t -> +-- | 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 maxT effect _d t = if t < maxT - then fn maxT t + then effect maxT t else id -overEnding :: Double -> Effect -> Effect -overEnding minT fn d t = +-- | 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 minT effect d t = if t >= blankDur - then fn minT (t-blankDur) + then effect minT (t-blankDur) else id where blankDur = d-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 start end effect _d t = + if start <= t && t <= end + then effect dur ((t - start) / dur) + else id + where + dur = end - start + +-- | @reverseE effect@ starts where the @effect@ ends and vice versa. reverseE :: Effect -> Effect reverseE fn = \d t -> fn d (d-t) -delayE :: Double -> Effect -> Effect +-- | Delay the effect so that it only starts after specified duration and then runs till the end of animation. +delayE :: Duration -> Effect -> Effect delayE delayT fn = \d t -> overEnding (d-delayT) fn d t +-- | 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 fn (Animation d genFrame) = Animation d $ \t -> fn d (d*t) $ genFrame t +-- | Build an effect from an image-modifying function. This effect does not change as time passes. constE :: (Tree -> Tree) -> Effect constE fn _d _t = fn +-- | Change image opacity from 0 to 1. fadeInE :: Effect fadeInE d t = withGroupOpacity (t/d) +-- | Change image opacity from 1 to 0. Reverse of 'fadeInE'. fadeOutE :: Effect fadeOutE = reverseE fadeInE +-- | Change stroke width from 0 to given value. fadeLineInE :: Double -> Effect fadeLineInE w d t = withStrokeWidth (w*(t/d)) +-- | Change stroke width from given value to 0. Reverse of 'fadeLineInE'. fadeLineOutE :: Double -> Effect fadeLineOutE = reverseE . fadeLineInE +-- | Effect of progressively drawing the image. Note that this will only affect primitive shapes (see 'pathify'). drawInE :: Effect drawInE d t = withFillOpacity 0 . partialSvg (t/d) . pathify +-- | Reverse of 'drawInE'. drawOutE :: Effect drawOutE = reverseE drawInE +-- | Change fill opacity from 0 to 1. fillInE :: Effect fillInE d t = withFillOpacity f where f = t/d +-- | Change scale from 1 to given value. scaleE :: Double -> Effect scaleE target d t = scale (1 + (target-1) * t/d) +-- | Move the image from its current position to the target x y coordinates. translateE :: Double -> Double -> Effect translateE x y d t = translate (x * t/d) (y * t/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 e d t = aroundCenter (e d t) diff --git a/src/Reanimate/Svg/Constructors.hs b/src/Reanimate/Svg/Constructors.hs index 826bf3b..e3b4eac 100644 --- a/src/Reanimate/Svg/Constructors.hs +++ b/src/Reanimate/Svg/Constructors.hs @@ -89,7 +89,7 @@ rotateAroundCenter a t = (x,y,w,h) = boundingBox t -- | @arounCenter f image@ first moves the image so the center of its bounding box is at the origin @(0, 0)@, --- applies transformation @f@ to it and then moves the transformed image to it's original position. +-- applies transformation @f@ to it and then moves the transformed image back to its original position. aroundCenter :: (Tree -> Tree) -> Tree -> Tree aroundCenter fn t = translate (-offsetX) (-offsetY) $ fn $ translate offsetX offsetY t @@ -104,7 +104,7 @@ aroundCenter fn t = scale :: Double -> Tree -> Tree scale a = withTransformations [Scale a Nothing] --- | @scaleToSize width height@ resizes the image so that it's bounding box has corresponding @width@ and @height@. +-- | @scaleToSize width height@ resizes the image so that its bounding box has corresponding @width@ and @height@. scaleToSize :: Double -> Double -> Tree -> Tree scaleToSize w h t = scaleXY (w/w') (h/h') t