Search code examples
haskellthreepenny-gui

Design a drawing api for Canvas


I am adding some function to threepenny ui api. I would like to had the ability to draw line with canvas.

The function that I can write have the following signature:

moveTo :: Vector -> UI ()
lineTo :: Vector -> UI ()
stroke :: UI ()
strokeStyle :: UI ()
beginPath :: UI ()

Each primitive moveTo and lineTo should happen in between a beginPath .. stroke call. How would you enforce the beginPath ... stroke sequence. By design I would like to give the user no choice for drawing lines. So the user is not aware of the beginPath ... stroke sequence.


Solution

  • Here's how I would design a canvas API.

    newtype Drawing = ...
    instance Monoid Drawing where ... -- for combining drawings
    
    line :: Vector -> Vector -> Drawing
    path :: [Vector] -> Drawing
    withStyle :: Style -> Drawing -> Drawing
    runDrawing :: Drawing -> UI ()
    

    Here the functions operate on semantically meaningful objects (from the user's perspective), rather than imperative commands. This should be implementable with the type

    newtype Drawing = Drawing (UI ())
    

    however sometimes subtleties will require that the type have a bit more structure, so be open to that (e.g. Something -> UI ()).