The approach that has worked for me is to use Reflex to render SVG . Reflex makes it fairly easy to render DOM objects to a web page and respond to mouse clicks on those objects. Using SVG ( instead of canvas ) allows for access to the rendered objects after the initial display, both for selection and for editing (resizing, moving, changing color, deletion).
Here are three "getting started" examples that use reflex/svg. Each of these includes a working demo ( linked to in the readme file ).
Render circles in locations determined by the circle-packing package
Interactive knight's tour animation.
Rotating 3D cube
Given that these examples are reflex based, they all are written using an FRP coding style but I tried to minimize the portion of each of these programs that specifically uses FRP techniques.
For example, the knight's tour and rotating cube both have a recursive-do block of code containing only calls to view, and update. In both cases, this block of code enables the feedback from view to accumulation of state changes ( foldDyn update )
From rotating cube example:
rec
view modelOrientation
modelOrientation <- foldDyn update initialOrientation tick
From knight's tour example:
rec
startEvent <- view width height rowCount colCount board tour
tour <- foldDyn (update board) [] $ leftmost [startEvent, advanceEvent]
The easiest way that I have found to get started with reflex is by cloning the reflex-platform github repository and running the try-reflex script contained in that repository - exactly as specified on the readme for reflex-platform
The circle-packing example requires the circle-packing package . The rotating 3d cube example requires the matrix package. To enable the use of these packages, include them in packages.nix in reflex-platform before running try-reflex - again, as specified on the reflex-platform readme.