Search code examples
haskellsvgreflex

a single svg element with reflex frp


I am trying to write a single SVG element within reflex FRP

import Reflex.Dom
import qualified Data.Map as Map

main = mainWidget $ myDiv

myDiv = el "svg" $ do
  elAttr "circle"  $ Map.fromList [ ("cx" , "50") , ("cy", "50"), ("r" , "40"), ("stroke" , "green"), ("fill",  "yellow" )]

This does not compile. Hoping Data.Map is correct. I know from the quickref the type signature is:

elAttr     :: String ->          Map String String  -> m a -> m a

Slightly curious what monad m is associated with mainWidget but mainly just getting to work.

This is compiled using the sandbox that comes with reflex.


Solution

  • There are two things to fix here.

    First, you want to return something, often the basic return () will allow you to compile.

    Second, the elAttr takes 2 input types, so after the "circle" you want to put the second argument in parenthesis rather than the $.

    This is what it looks like:

    import Reflex.Dom
    import qualified Data.Map as Map
    
    main = mainWidget $ myDiv
    
    myDiv = el "svg" $ do
      elAttr "circle"  (Map.fromList [ ("cx" , "50") , ("cy", "50"), ("r" , "40"), ("stroke" , "green"), ("fill",  "yellow" )]) $ return ()
    

    After compiling, you should be able to see this in your browser's element inspector.

    <html>
      <head>
        <script language="javascript" src="rts.js"></script>
        <script language="javascript" src="lib.js"></script>
        <script language="javascript" src="out.js"></script>
      </head>
      <body>
        <svg>
         <circle cx="50" cy="50" fill="yellow" r="40" stroke="green"></circle>
        </svg>
      </body>
    </html>
    

    If you want to see it show up in the browser, make sure to define this attribute xmlns="http://www.w3.org/20000/svg" in your svg element like below with elDynAttrNS':

    main = mainWidget $ myDiv
    
    myDiv = do
      let attrs = constDyn $ fromList
                   [ ("width" , "500")
                   , ("height" , "250")
                   ]
      let cAttrs = constDyn $ fromList
                   [ ("cx", "50")
                   , ("cy", "50")
                   , ("r", "40")
                   , ("stroke", "green")
                   , ("stroke-width", "3")
                   , ("fill",  "yellow" )
                   ]
    
      s <- elSvg "svg" attrs (elSvg "circle" cAttrs (return ()))
      return ()
    
    elSvg tag a1 a2 = do
      elDynAttrNS' ns tag a1 a2
      return ()
    
    ns :: Maybe String
    ns = Just "http://www.w3.org/2000/svg"