From 51192f84ccb11811d30756b31718828decb1e99d Mon Sep 17 00:00:00 2001 From: David Date: Thu, 14 Feb 2019 16:44:10 +0100 Subject: [PATCH] Update examples. --- README.md | 118 ++++++++++++++++++++++++++++++++++ src/Reanimate/Combinators.hs | 3 + src/Reanimate/Examples.hs | 120 ++++++++++++----------------------- src/SvgViewer.hs | 2 +- 4 files changed, 163 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index a6802ec..e2982c9 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,135 @@ # reanimate + + # Examples +## Sine wave + +``` +sinewave :: Ani () +sinewave = proc () -> do + duration 10 -< () + emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] + + idx <- signalOscillate 0 1 -< () + emit -< do + defs_ $ clipPath_ [id_ "clip"] $ + rect_ [x_ "0", num_ y_ (-height), num_ width_ (idx * width), height_ "100%"] + g_ [transform_ $ translate margin height, clip_path_ "url(#clip)"] $ + renderPath $ approxFnData 1000 wave + line_ [ num_ x1_ margin, num_ x2_ margin, y1_ "10", y2_ "170" + , stroke_ "white"] + line_ [num_ x1_ margin, num_ x2_ (margin+width), num_ y1_ height, num_ y2_ height + , stroke_ "white"] + + circX <- signalOscillate margin (width+margin) -< () + let circY = height + sin (idx*pi*2*freq) * 50 + emit -< circle_ [num_ cx_ circX, num_ cy_ circY, r_ "3", fill_ "red"] + where + freq = 3; margin = 30; width = 260; height = 90 + wave idx = (idx*width, sin (idx*pi*2*freq) * 50) +``` ![Sine wave](gifs/sinewave.gif) + +## Morphing wave + +``` +morph_wave :: Ani () +morph_wave = proc () -> do + duration 5 -< () + emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] + + morph <- signalOscillate 0 1 -< () + emit -< do + g_ [transform_ $ translate 30 50] $ renderPath wave1 + g_ [transform_ $ translate 30 130] $ renderPath wave2 + g_ [transform_ $ translate 30 90] $ renderPath $ morphPath wave1 wave2 morph + line_ [x1_ "30", x2_ "30", y1_ "10", y2_ "170", stroke_ "white"] + line_ [x1_ "30", x2_ "290", y1_ "90", y2_ "90", stroke_ "white"] + where + freq = 3; width = 260 + wave1 = approxFnData 1000 $ \idx -> (idx*width, sin (idx*pi*2*freq) * 20) + wave2 = approxFnData 1000 $ \idx -> (idx*width, sin (idx*pi*2*(freq*3)) * 20) +``` ![Morphing wave](gifs/morphwave.gif) + +## Morph wave to circle + +``` +morph_wave_circle :: Ani () +morph_wave_circle = proc t -> do + duration 5 -< () + emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] + + idx <- signalOscillate 0 1 -< () + emit -< do + g_ [transform_ $ translate 30 90] $ + renderPath $ morphPath circle wave1 idx + line_ [x1_ "30", x2_ "30", y1_ "10", y2_ "170", stroke_ "white"] + line_ [x1_ "30", x2_ "290", y1_ "90", y2_ "90", stroke_ "white"] + where + freq = 5; width = 260; radius = 50 + wave1 = approxFnData 1000 $ \idx -> (idx*width, sin (idx*pi*2*freq) * 20) + circle = approxFnData 1000 $ \idx -> + (cos (idx*pi*2+pi/2)*radius + width/2, sin (idx*pi*2+pi/2)*radius) +``` ![Morphing wave to circle](gifs/morphwave_circle.gif) +## Speed modification + +``` +progressMeters :: Ani () +progressMeters = proc () -> do + emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] + annotate' (adjustSpeed 1.0 progressMeter) -< g_ [transform_ $ translate 40 20] + annotate' (adjustSpeed 2.0 progressMeter) -< g_ [transform_ $ translate 140 20] + annotate' (adjustSpeed 0.5 progressMeter) -< g_ [transform_ $ translate 240 20] + + emit -< do + text_ [x_ "55", y_ "150", font_size_ "20" + , text_anchor_ "middle" + , fill_ "white"] "1x" + text_ [x_ "155", y_ "150", font_size_ "20" + , text_anchor_ "middle" + , fill_ "white"] "2x" + text_ [x_ "255", y_ "150", font_size_ "20" + , text_anchor_ "middle" + , fill_ "white"] "0.5x" +``` ![Speed modification](gifs/progress.gif) +## Highlights ![Highlight](gifs/highlight.gif) +## Clipping + +``` +clip_rect :: Ani () +clip_rect = proc () -> do + emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] + follow + [ proc () -> do + sim [ paintStatic prev | prev <- [max 0 (n-4) .. n-1] ] -< () + sim [ runAni "black" i | i <- [n-4], i>=0 ] -< () + runAni "white" n -< () + | n <- [0..15] + ] -< () + where + paintStatic nth = proc () -> + annotate' (obj "white" (20+nth*10) (20+nth*10)) + -< g_ [transform_ $ translate 160 90] + runAni color nth = proc () -> + annotate' (defineAnimation $ circle_clip (obj color (20+nth*10) (20+nth*10))) + -< g_ [transform_ $ translate 160 90] + obj c width height = proc () -> do + duration 1 -< () + emit -< rect_ [ num_ width_ width, num_ height_ height + , num_ x_ (-width/2), num_ y_ (-height/2) + , stroke_ c, fill_opacity_ "0", stroke_width_ "2" ] +``` ![Clipping](gifs/clip_rect.gif) diff --git a/src/Reanimate/Combinators.hs b/src/Reanimate/Combinators.hs index 408d361..367163d 100644 --- a/src/Reanimate/Combinators.hs +++ b/src/Reanimate/Combinators.hs @@ -153,3 +153,6 @@ sync (Animation d1 fn1) (Animation d2 fn2) = syncAll :: [Ani ()] -> Ani () syncAll = foldl sync (arr (pure ())) + +num_ :: (Show a, Num a) => (Text -> Attribute) -> (a -> Attribute) +num_ attr n = attr (pack (show n)) diff --git a/src/Reanimate/Examples.hs b/src/Reanimate/Examples.hs index ec49c82..7709741 100644 --- a/src/Reanimate/Examples.hs +++ b/src/Reanimate/Examples.hs @@ -11,78 +11,45 @@ import Reanimate.Combinators import Debug.Trace -test1 :: Ani () -test1 = - fade 1 $ - proc t -> do - duration 10 -< t - emit -< circle_ [cx_ "160", cy_ "90", r_ "50", fill_ "blue"] - -test2 :: Ani () -test2 = proc t -> do - duration 5 -< t - emit -< rect_ [width_ "100%", height_ "100%", fill_ "red", r_ (pack $ show t)] - sinewave :: Ani () sinewave = proc () -> do - duration 10 -< () - emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] - t <- getTime -< () + duration 10 -< () + emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] - idx <- signalOscillate 0 1 -< () - let clipWidth = pack $ show $ idx * 260 - emit -< defs_ $ clipPath_ [id_ "clip"] $ rect_ [x_ "0", y_ "-90", width_ clipWidth, height_ "100%"] - annotate (g_ [transform_ $ translate 30 90]) $ - annotate (g_ [clip_path_ "url(#clip)"]) $ - approxFn 1000 (\idx -> - let xValue = idx*260 - yValue = sin (idx*pi*2*freq) * 50 - in (xValue, yValue)) -< () - emit -< line_ [x1_ "30", x2_ "30", y1_ "10", y2_ "170", stroke_ "white"] - emit -< line_ [x1_ "30", x2_ "290", y1_ "90", y2_ "90", stroke_ "white"] + idx <- signalOscillate 0 1 -< () + emit -< do + defs_ $ clipPath_ [id_ "clip"] $ + rect_ [x_ "0", num_ y_ (-height), num_ width_ (idx * width), height_ "100%"] + g_ [transform_ $ translate margin height, clip_path_ "url(#clip)"] $ + renderPath $ approxFnData 1000 wave + line_ [ num_ x1_ margin, num_ x2_ margin, y1_ "10", y2_ "170" + , stroke_ "white"] + line_ [num_ x1_ margin, num_ x2_ (margin+width), num_ y1_ height, num_ y2_ height + , stroke_ "white"] - circX <- signalOscillate 30 290 -< () - let circY = pack $ show $ 90 + sin (idx*pi*2*freq) * 50 - - emit -< circle_ [cx_ (pack (show circX)), cy_ circY, r_ "3", fill_ "red"] - returnA -< () + circX <- signalOscillate margin (width+margin) -< () + let circY = height + sin (idx*pi*2*freq) * 50 + emit -< circle_ [num_ cx_ circX, num_ cy_ circY, r_ "3", fill_ "red"] where - freq = 3 + freq = 3; margin = 30; width = 260; height = 90 + wave idx = (idx*width, sin (idx*pi*2*freq) * 50) morph_wave :: Ani () morph_wave = proc () -> do - duration 5 -< () - emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] + duration 5 -< () + emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] - emit -< - g_ [transform_ $ translate 30 50] $ - renderPath wave1 - emit -< - g_ [transform_ $ translate 30 130] $ - renderPath wave2 - - morph <- signalOscillate 0 1 -< () - emit -< - g_ [transform_ $ translate 30 90] $ - renderPath $ morphPath wave1 wave2 morph - - emit -< line_ [x1_ "30", x2_ "30", y1_ "10", y2_ "170", stroke_ "white"] - emit -< line_ [x1_ "30", x2_ "290", y1_ "90", y2_ "90", stroke_ "white"] - - returnA -< () + morph <- signalOscillate 0 1 -< () + emit -< do + g_ [transform_ $ translate 30 50] $ renderPath wave1 + g_ [transform_ $ translate 30 130] $ renderPath wave2 + g_ [transform_ $ translate 30 90] $ renderPath $ morphPath wave1 wave2 morph + line_ [x1_ "30", x2_ "30", y1_ "10", y2_ "170", stroke_ "white"] + line_ [x1_ "30", x2_ "290", y1_ "90", y2_ "90", stroke_ "white"] where - myD = animationDuration morph_wave - freq = 1/2 - wave1 = approxFnData 1000 (\idx -> - let xPos = idx*260 - xValue = idx*myD - yValue = sin (xValue*pi*2*freq) * 20 - in (xPos, yValue)) - wave2 = approxFnData 1000 (\idx -> - let xPos = idx*260 - xValue = idx*myD - yValue = sin (xValue*pi*2*(freq*3)) * 20 - in (xPos, yValue)) + freq = 3; width = 260 + wave1 = approxFnData 1000 $ \idx -> (idx*width, sin (idx*pi*2*freq) * 20) + wave2 = approxFnData 1000 $ \idx -> (idx*width, sin (idx*pi*2*(freq*3)) * 20) morph_wave_circle :: Ani () morph_wave_circle = proc t -> do @@ -90,27 +57,22 @@ morph_wave_circle = proc t -> do emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] idx <- signalOscillate 0 1 -< () - emit -< + emit -< do g_ [transform_ $ translate 30 90] $ - renderPath $ morphPath circle wave1 idx - emit -< line_ [x1_ "30", x2_ "30", y1_ "10", y2_ "170", stroke_ "white"] - emit -< line_ [x1_ "30", x2_ "290", y1_ "90", y2_ "90", stroke_ "white"] - - returnA -< () + renderPath $ morphPath circle wave1 idx + line_ [x1_ "30", x2_ "30", y1_ "10", y2_ "170", stroke_ "white"] + line_ [x1_ "30", x2_ "290", y1_ "90", y2_ "90", stroke_ "white"] where - freq = 5 - wave1 = approxFnData 1000 (\idx -> - let xValue = idx*260 - yValue = sin (idx*pi*2*freq) * 20 - in (xValue, yValue)) + freq = 5; width = 260; radius = 50 + wave1 = approxFnData 1000 $ \idx -> (idx*width, sin (idx*pi*2*freq) * 20) circle = approxFnData 1000 $ \idx -> - (cos (idx*pi*2+pi/2)*50 + 130, sin (idx*pi*2+pi/2)*50) + (cos (idx*pi*2+pi/2)*radius + width/2, sin (idx*pi*2+pi/2)*radius) progressMeters :: Ani () progressMeters = proc () -> do emit -< rect_ [width_ "100%", height_ "100%", fill_ "black"] - annotate' progressMeter -< g_ [transform_ $ translate 40 20] - annotate' (adjustSpeed 2 progressMeter) -< g_ [transform_ $ translate 140 20] + annotate' (adjustSpeed 1.0 progressMeter) -< g_ [transform_ $ translate 40 20] + annotate' (adjustSpeed 2.0 progressMeter) -< g_ [transform_ $ translate 140 20] annotate' (adjustSpeed 0.5 progressMeter) -< g_ [transform_ $ translate 240 20] emit -< do @@ -129,7 +91,7 @@ progressMeter = loop $ defineAnimation $ proc () -> do duration 5 -< () h <- signal 0 100 -< () emit -< rect_ [ width_ "30", height_ "100", stroke_ "white", stroke_width_ "2", fill_opacity_ "0" ] - emit -< rect_ [ width_ "30", height_ (pack $ show h), stroke_ "white", fill_ "white" ] + emit -< rect_ [ width_ "30", num_ height_ h, stroke_ "white", fill_ "white" ] returnA -< () highlight :: Ani () @@ -200,8 +162,8 @@ clip_rect = proc () -> do -< g_ [transform_ $ translate 160 90] obj c width height = proc () -> do duration 1 -< () - emit -< rect_ [ width_ $ pack $ show width, height_ $ pack $ show height - , x_ $ pack $ show (-width/2), y_ $ pack $ show (-height/2) + emit -< rect_ [ num_ width_ width, num_ height_ height + , num_ x_ (-width/2), num_ y_ (-height/2) , stroke_ c, fill_opacity_ "0", stroke_width_ "2" ] circle_clip :: Ani () -> Ani () diff --git a/src/SvgViewer.hs b/src/SvgViewer.hs index 4906bad..35ba639 100644 --- a/src/SvgViewer.hs +++ b/src/SvgViewer.hs @@ -15,7 +15,7 @@ import Data.Time import Reanimate.Arrow import Reanimate.Examples -animation = scaling +animation = progressMeters main :: IO () main = do