svg with reflex

Filed under: haskell

A friend needed help figuring out why code didn’t compile when creating an SVG element with reflexfrp.

I explained how the element creation requires a specific format.

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 ()

It is basically saying create a svg tag, with the specified attributes. elAttr has a type signature of elAttr :: String -> Map String String -> m a -> m a, which if you match would mean that there are two inputs.

The first input: String is "circle"

and the second input: Map String String is everything inside the parentheses Map.fromList [ ("cx" , "50") , ("cy", "50"), ("r" , "40"), ("stroke" , "green"), ("fill", "yellow" )]

The second input should be wrapped with parentheses () so that the type signatures match. I’m not sure exactly why the syntax works like this however that is what the compiler needs to see to understand.

Once compiled the output would look like this:

<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>

Final note, to have SVGs show up in the browser, you need to define the xmlns attribute:

<svg xmlns="http://www.w3.org/2000/svg">
  <circle cx="50px" cy="50" fill="yellow" r="40" stroke="green"></circle>
</svg>

The end result is a yellow circle: