shine: Declarative graphics for the browser using GHCJS

[ graphics, javascript, library, mit, web ] [ Propose Tags ]

Shine wraps javascript's drawing functions in a declarative API. Heavily inspired by Gloss.

Read the README for an overview of the library.


[Skip to Readme]
Versions [faq] 0.1.0.0, 0.2.0.0, 0.2.0.1, 0.2.0.2, 0.2.0.3
Dependencies base (>=4.2 && <5), ghcjs-dom (==0.2.*), ghcjs-prim, keycode, mtl, time, transformers [details]
License MIT
Copyright (c) 2016 Francesco Gazzetta
Author Francesco Gazzetta
Maintainer Francesco Gazzetta <francygazz@gmail.com>
Revised Revision 2 made by fgaz at Thu Jun 22 23:21:14 UTC 2017
Category Web, Graphics, Javascript
Home page https://github.com/fgaz/shine
Bug tracker https://github.com/fgaz/shine/issues
Source repo head: git clone https://github.com/fgaz/shine.git
Uploaded by fgaz at Wed Apr 20 17:20:28 UTC 2016
Distributions NixOS:0.2.0.3
Downloads 1436 total (7 in the last 30 days)
Rating 2.25 (votes: 2) [estimated by rule of succession]
Your Rating
  • λ
  • λ
  • λ
Status Hackage Matrix CI
Docs uploaded by user
Build status unknown [no reports yet]

Modules

[Index]

Downloads

Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

For package maintainers and hackage trustees


Readme for shine-0.1.0.0

[back to package description]

Shine - Declarative Graphics for the Web

Shine wraps javascript's drawing functions in a declarative API.

Heavily inspired by gloss.

Compiling

You need ghcjs

Usage

Pictures

To represent your drawing you have to build a tree using the Picture datatype.

pic :: Picture
pic = Rect 10 20 -- represents a 10x20 square

To compose multiple Pictures you can use Over, which accepts two Pictures and overlaps them.

Picture is a monoid: <> is an alias for Over and mempty is the empty picture.

-- draw some shapes on top of each other
pic :: Picture
pic = Rect 10 20
   <> Translate 30 30 (Circle 15)
   <> Colored (Color 255 0 0 0.2) (RectF 4 4)
   <> Text "Sans 12px" LeftAlign 200 "The quick brown fox jumps over the lazy dog."

Using Foldable you can do things like

concentricCircles :: Picture
concentricCircles = foldMap Circle [1,10..100]

Drawing Pictures

Before drawing anything you need to obtain a CanvasRenderingContext2D. For this purpose, shine provides two utility functions: fullScreenCanvas and fixedSizeCanvas

main :: IO ()
main = runWebGUI $ \ webView -> do
    ctx <- fixedSizeCanvas webView 800 600
    -- do something with ctx

To render a Picture on a context you have three options:

render

You can draw it manually using render from Graphics.Shine.Render

main :: IO ()
main = runWebGUI $ \ webView -> do
    ctx <- fixedSizeCanvas webView 400 400
    draw ctx concentricCircles

animate

You can draw a Picture that depends on time. That is, a Float -> Picture.

-- An expanding-and-contracting circle.
animation :: Float -> Picture
animation = Translate 200 200
          . Circle
          . (*100) . (+1) -- bigger positive oscillation
          . sin -- the circle's radius oscillates

main :: IO ()
main = runWebGUI $ \ webView -> do
    ctx <- fixedSizeCanvas webView 400 400
    animate ctx 30 animation

play

Finally, you can draw a Picture that depends on time, inputs (keyboard and mouse) and an internal state. This is especially useful for games, hence the name.

-- this code draws a black rectangle in the center of the canvas only when the
-- left mouse button is pressed
main :: IO ()
main = runWebGUI $ \ webView -> do
    ctx <- fixedSizeCanvas webView 400 400
    Just doc <- webViewGetDomDocument webView
    play ctx doc 30 initialState draw handleInput step
  where
    -- our state represents the state of the left mouse button
    initialState = Up
    -- we draw a square only if the button is pressed
    draw Up = Empty
    draw Down = Translate 200 200 $ RectF 200 200
    -- when an event is fired we store the button state
    handleInput (MouseBtn BtnLeft buttonState _) = const buttonState
    handleInput _ = id -- catch-all for all other events
    step _ = id -- our state does not depend on time