fay-0.4.0.4: examples/canvaswater.hs
-- | Compile with: dist/build/fay/fay -autorun examples/canvaswater.hs
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE NoImplicitPrelude #-}
-- | A demonstration of Fay using the canvas element to display a
-- simple effect.
module CanvasWater (main) where
import Language.Fay.FFI
import Language.Fay.Prelude
-- | Main entry point.
main :: Fay ()
main = do
img <- newImage
addEventListener img "load" (start img) False
setSrc img "haskell.png"
-- | Start the animation.
start :: Image -> Fay ()
start img = do
canvas <- getElementById "can"
context <- getContext canvas "2d"
drawImage context img 0 0
step <- newRef (0 :: Double)
setInterval (animate context img step) 30
-- | Animate the water effect.
animate :: Context -> Image -> Ref Double -> Fay ()
animate context img step = do
stepn <- readRef step
setFillStyle context "rgb(255,255,255)"
forM_ [0..imgHeight] $ \i ->
drawImageSpecific context img
0 0
imgWidth imgHeight
(sin(3*(stepn+i/20.0))*(i/2.0)) (140+i)
imgWidth imgHeight
writeRef step (stepn + 0.05)
imgHeight = 140
imgWidth = 200
--------------------------------------------------------------------------------
-- Elements
class Eventable a
-- | A DOM element.
data Element
instance Foreign Element
instance Eventable Element
-- | Add an event listener to an element.
addEventListener :: (Foreign a,Eventable a) => a -> String -> Fay () -> Bool -> Fay ()
addEventListener = ffi "%1['addEventListener'](%2,%3,%4)" FayNone
-- | Get an element by its ID.
getElementById :: String -> Fay Element
getElementById = ffi "document['getElementById'](%1)" FayNone
--------------------------------------------------------------------------------
-- Images
data Image
instance Foreign Image
instance Eventable Image
-- | Make a new image.
newImage :: Fay Image
newImage = ffi "new Image()" FayNone
-- | Make a new image.
setSrc :: Image -> String -> Fay ()
setSrc = ffi "%1['src'] = %2" FayNone
--------------------------------------------------------------------------------
-- Canvas
-- | A canvas context.
data Context
instance Foreign Context
-- | Get an element by its ID.
getContext :: Element -> String -> Fay Context
getContext = ffi "%1['getContext'](%2)" FayNone
-- | Draw an image onto a canvas rendering context.
drawImage :: Context -> Image -> Double -> Double -> Fay ()
drawImage = ffi "%1['drawImage'](%2,%3,%4)" FayNone
-- | Draw an image onto a canvas rendering context.
--
-- Nine arguments: the element, source (x,y) coordinates, source width and
-- height (for cropping), destination (x,y) coordinates, and destination width
-- and height (resize).
--
-- context.drawImage(img_elem, sx, sy, sw, sh, dx, dy, dw, dh);
drawImageSpecific :: Context -> Image
-> Double -> Double -> Double -> Double -> Double -> Double -> Double -> Double
-> Fay ()
drawImageSpecific = ffi "%1['drawImage'](%2,%3,%4,%5,%6,%7,%8,%9,%10)" FayNone
-- | Set the fill style.
setFillStyle :: Context -> String -> Fay ()
setFillStyle = ffi "%1['fillStyle']=%2" FayNone
-- | Set the fill style.
setFillRect :: Context -> Double -> Double -> Double -> Double -> Fay ()
setFillRect = ffi "%1['fillRect'](%2,%3,%4,%5)" FayNone
--------------------------------------------------------------------------------
-- Ref
-- | A mutable reference like IORef.
data Ref a
instance Foreign a => Foreign (Ref a)
-- | Make a new mutable reference.
newRef :: Foreign a => a -> Fay (Ref a)
newRef = ffi "new Fay$$Ref(%1)" FayNone
-- | Replace the value in the mutable reference.
writeRef :: Foreign a => Ref a -> a -> Fay ()
writeRef = ffi "Fay$$writeRef(%1,%2)" FayNone
-- | Get the referred value from the mutable value.
readRef :: Foreign a => Ref a -> Fay a
readRef = ffi "Fay$$readRef(%1)" FayNone
--------------------------------------------------------------------------------
-- Misc
-- | Alert using window.alert.
alert :: Foreign a => a -> Fay ()
alert = ffi "window['alert'](%1)" FayNone
-- | Alert using window.alert.
print :: Double -> Fay ()
print = ffi "console['log'](%1)" FayNone
-- | Alert using window.alert.
log :: String -> Fay ()
log = ffi "console['log'](%1)" FayNone
-- | Alert using window.alert.
sin :: Double -> Double
sin = ffi "window.Math['sin'](%1)" FayNone
-- | Alert using window.alert.
setInterval :: Fay () -> Double -> Fay ()
setInterval = ffi "window['setInterval'](%1,%2)" FayNone