Document Reanimate.Effect, add overInterval.

Former-commit-id: 2dd9a3589a045126ab857807cca601495bd6bb7a
This commit is contained in:
Jan Hrček 2020-01-11 18:28:58 +01:00 committed by David Himmelstrup
commit 703836bc89
3 changed files with 79 additions and 12 deletions

View file

@ -86,6 +86,7 @@ module Reanimate
Effect, Effect,
overBeginning, overBeginning,
overEnding, overEnding,
overInterval,
reverseE, reverseE,
delayE, delayE,
applyE, applyE,
@ -97,6 +98,7 @@ module Reanimate
drawInE, drawInE,
drawOutE, drawOutE,
fillInE, fillInE,
scaleE,
translateE, translateE,
aroundCenterE, aroundCenterE,
transitions, transitions,

View file

@ -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 Graphics.SvgTree (Tree)
import Reanimate.Animation import Reanimate.Animation
import Reanimate.Svg 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 -- | Modify the effect so that it only applies to the initial part of the animation.
overBeginning maxT fn = \_d t -> 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 if t < maxT
then fn maxT t then effect maxT t
else id else id
overEnding :: Double -> Effect -> Effect -- | Modify the effect so that it only applies to the ending part of the animation.
overEnding minT fn d t = 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 if t >= blankDur
then fn minT (t-blankDur) then effect minT (t-blankDur)
else id else id
where where
blankDur = d-minT 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 :: Effect -> Effect
reverseE fn = \d t -> fn d (d-t) 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 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 :: Effect -> Animation -> Animation
applyE fn (Animation d genFrame) = Animation d $ \t -> fn d (d*t) $ genFrame t 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 :: (Tree -> Tree) -> Effect
constE fn _d _t = fn constE fn _d _t = fn
-- | Change image opacity from 0 to 1.
fadeInE :: Effect fadeInE :: Effect
fadeInE d t = withGroupOpacity (t/d) fadeInE d t = withGroupOpacity (t/d)
-- | Change image opacity from 1 to 0. Reverse of 'fadeInE'.
fadeOutE :: Effect fadeOutE :: Effect
fadeOutE = reverseE fadeInE fadeOutE = reverseE fadeInE
-- | Change stroke width from 0 to given value.
fadeLineInE :: Double -> Effect fadeLineInE :: Double -> Effect
fadeLineInE w d t = withStrokeWidth (w*(t/d)) fadeLineInE w d t = withStrokeWidth (w*(t/d))
-- | Change stroke width from given value to 0. Reverse of 'fadeLineInE'.
fadeLineOutE :: Double -> Effect fadeLineOutE :: Double -> Effect
fadeLineOutE = reverseE . fadeLineInE fadeLineOutE = reverseE . fadeLineInE
-- | Effect of progressively drawing the image. Note that this will only affect primitive shapes (see 'pathify').
drawInE :: Effect drawInE :: Effect
drawInE d t = withFillOpacity 0 . partialSvg (t/d) . pathify drawInE d t = withFillOpacity 0 . partialSvg (t/d) . pathify
-- | Reverse of 'drawInE'.
drawOutE :: Effect drawOutE :: Effect
drawOutE = reverseE drawInE drawOutE = reverseE drawInE
-- | Change fill opacity from 0 to 1.
fillInE :: Effect fillInE :: Effect
fillInE d t = withFillOpacity f fillInE d t = withFillOpacity f
where where
f = t/d f = t/d
-- | Change scale from 1 to given value.
scaleE :: Double -> Effect scaleE :: Double -> Effect
scaleE target d t = scale (1 + (target-1) * t/d) 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 :: Double -> Double -> Effect
translateE x y d t = translate (x * t/d) (y * t/d) 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 :: Effect -> Effect
aroundCenterE e d t = aroundCenter (e d t) aroundCenterE e d t = aroundCenter (e d t)

View file

@ -89,7 +89,7 @@ rotateAroundCenter a t =
(x,y,w,h) = boundingBox 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)@, -- | @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 :: (Tree -> Tree) -> Tree -> Tree
aroundCenter fn t = aroundCenter fn t =
translate (-offsetX) (-offsetY) $ fn $ translate offsetX offsetY t translate (-offsetX) (-offsetY) $ fn $ translate offsetX offsetY t
@ -104,7 +104,7 @@ aroundCenter fn t =
scale :: Double -> Tree -> Tree scale :: Double -> Tree -> Tree
scale a = withTransformations [Scale a Nothing] 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 :: Double -> Double -> Tree -> Tree
scaleToSize w h t = scaleToSize w h t =
scaleXY (w/w') (h/h') t scaleXY (w/w') (h/h') t