diff --git a/README.md b/README.md index 1ad2671..aed1365 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,25 @@ bbox2 = defineAnimation $ proc () -> do ``` ![Bounding boxes](gifs/bbox.gif) +## Colorful LaTeX +```haskell +latex_color :: Ani () +latex_color = proc () -> do + duration 0.1 -< () + emit -< toHtml $ mkBackground "black" + emit -< toHtml $ translate (320/2) (180/2) $ withStrokeWidth (Num 0.2) $ + withStrokeColor "white" $ + withSubglyphs 0 1 (withFillColor "blue") $ + withSubglyphs 1 2 (withFillColor "yellow") $ + withSubglyphs 2 3 (withFillColor "green") $ + withSubglyphs 3 4 (withFillColor "red") $ + withSubglyphs 4 5 (withFillColor "darkslategrey") $ + svg + where + svg = scale 10 $ center $ latex "\\LaTeX" +``` +![Colorful LaTeX](gifs/latex_color.gif) + ## Bezier curves ![Bezier curves](gifs/bezier.gif) diff --git a/gifs/latex_color.gif b/gifs/latex_color.gif new file mode 100644 index 0000000..b5bba0c Binary files /dev/null and b/gifs/latex_color.gif differ diff --git a/src/Reanimate/Examples.hs b/src/Reanimate/Examples.hs index 157c2a7..d706252 100644 --- a/src/Reanimate/Examples.hs +++ b/src/Reanimate/Examples.hs @@ -478,3 +478,18 @@ heartShape = "M0.0,40.0 v-40.0 h40.0\ \a20.0 20.0 90.0 0 1 0.0,40.0\ \a20.0 20.0 90.0 0 1 -40.0,0.0 Z" + +latex_color :: Ani () +latex_color = proc () -> do + duration 0.1 -< () + emit -< toHtml $ mkBackground "black" + emit -< toHtml $ translate (320/2) (180/2) $ withStrokeWidth (Num 0.2) $ + withStrokeColor "white" $ + withSubglyphs 0 1 (withFillColor "blue") $ + withSubglyphs 1 2 (withFillColor "yellow") $ + withSubglyphs 2 3 (withFillColor "green") $ + withSubglyphs 3 4 (withFillColor "red") $ + withSubglyphs 4 5 (withFillColor "darkslategrey") $ + svg + where + svg = scale 10 $ center $ latex "\\LaTeX" diff --git a/src/Reanimate/Svg.hs b/src/Reanimate/Svg.hs index a9b957a..59a69ca 100644 --- a/src/Reanimate/Svg.hs +++ b/src/Reanimate/Svg.hs @@ -340,14 +340,8 @@ svgBoundingPoints t = map (Transform.transformPoint m) $ mapTuple f = f *** f withTransformations :: [Transformation] -> Tree -> Tree -withTransformations transformations = withDrawAttributes (transform .~ Just transformations) - -withDrawAttributes :: (DrawAttributes -> DrawAttributes) -> Tree -> Tree -withDrawAttributes lens tree = GroupTree $ defaultSvg - & drawAttr .~ attr - & groupChildren .~ [tree] - where - attr = defaultSvg & lens +withTransformations transformations t = + mkGroup [t] & drawAttr %~ transform .~ Just transformations translate :: Double -> Double -> Tree -> Tree translate x y = withTransformations [Translate x y] @@ -411,19 +405,19 @@ mkColor name = Just c -> ColorRef c withStrokeColor :: String -> Tree -> Tree -withStrokeColor color = withDrawAttributes (strokeColor .~ pure (mkColor color)) +withStrokeColor color = drawAttr %~ strokeColor .~ pure (mkColor color) withFillColor :: String -> Tree -> Tree -withFillColor color = withDrawAttributes (fillColor .~ pure (mkColor color)) +withFillColor color = drawAttr %~ fillColor .~ pure (mkColor color) withFillOpacity :: Double -> Tree -> Tree -withFillOpacity opacity = withDrawAttributes (fillOpacity .~ Just (realToFrac opacity)) +withFillOpacity opacity = drawAttr %~ fillOpacity .~ Just (realToFrac opacity) withStrokeWidth :: Number -> Tree -> Tree -withStrokeWidth width = withDrawAttributes (strokeWidth .~ pure width) +withStrokeWidth width = drawAttr %~ strokeWidth .~ pure width withClipPathRef :: ElementRef -> Tree -> Tree -withClipPathRef ref = withDrawAttributes (clipPathRef .~ pure ref) +withClipPathRef ref = drawAttr %~ clipPathRef .~ pure ref mkRect :: Point -> Number -> Number -> Tree mkRect corner width height = RectangleTree $ defaultSvg @@ -451,3 +445,27 @@ mkPathText str = mkBackground :: String -> Tree mkBackground color = withFillColor color $ mkRect (Num 0, Num 0) (Percent 100) (Percent 100) + +withSubglyphs :: Int -> Int -> (Tree -> Tree) -> Tree -> Tree +withSubglyphs from to fn t = evalState (worker t) 0 + where + worker :: Tree -> State Int Tree + worker t = + case t of + GroupTree g -> do + cs <- mapM worker (g ^. groupChildren) + return $ GroupTree $ g & groupChildren .~ cs + PathTree{} -> handleGlyph t + CircleTree{} -> handleGlyph t + PolyLineTree{} -> handleGlyph t + PolygonTree{} -> handleGlyph t + EllipseTree{} -> handleGlyph t + LineTree{} -> handleGlyph t + RectangleTree{} -> handleGlyph t + _ -> return t + handleGlyph :: Tree -> State Int Tree + handleGlyph t = do + n <- get <* modify (+1) + if n >= from && n < to + then return $ fn t + else return t