<div dir="ltr"><div style="" class="markdown-here-wrapper"><p style="margin:1.2em 0px!important">Shine wraps JavaScript’s drawing functions in a declarative API, hiding the boilerplate canvas code.</p>
<p style="margin:1.2em 0px!important">The API mimics the one provided by gloss (<code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">Picture</code>, <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">animate</code>, <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">play</code>…), but some types are different to better adapt to js code (ex. images, fonts, inputs).</p>
<p style="margin:1.2em 0px!important">Example:  </p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,255) none repeat scroll 0% 0%">main = runWebGUI $ \ webView -> do
    ctx <- fixedSizeCanvas webView 800 600
    let concentricCircles = foldMap Circle [1,10..100]
    draw ctx concentricCircles -- one-shot drawing
</code></pre><p style="margin:1.2em 0px!important">The only direct dependency is ghcjs-dom, so the resulting jsexe should be relatively lightweight.</p>
<p style="margin:1.2em 0px!important">I also wrote shine-varying, a FRP interface to shine in terms of Vars plus some utility Vars.</p>
<p style="margin:1.2em 0px!important">Example (translation of the resize-yogi Elm example):  </p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,255) none repeat scroll 0% 0%">resizeImage img (x',y') = Translate (x/2) (y/2) -- Pictures are centered on (0,0), so we need to move it
                        $ Image (Stretched x y) img -- Scale the picture to the given position
  where
    x = fromIntegral x' -- mousePosition is Integral
    y = fromIntegral y'

main = runWebGUI $ \ webView -> do
    ctx <- fixedSizeCanvas webView 1024 768
    Just doc <- webViewGetDomDocument webView
    narwhal <- makeImage "<a href="https://wiki.haskell.org/wikiupload/8/85/NarleyYeeaaahh.jpg">https://wiki.haskell.org/wikiupload/8/85/NarleyYeeaaahh.jpg</a>"
    let resizedNarwhal = resizeImage narwhal <$> mousePosition
    playVarying ctx doc 30 resizedNarwhal
</code></pre><p style="margin:1.2em 0px!important">I plan to write/port a few simple games with it soon.</p>
<p style="margin:1.2em 0px!important">Francesco</p>
<div title="MDH:PGRpdj5TaGluZSB3cmFwcyBKYXZhU2NyaXB0J3MgZHJhd2luZyBmdW5jdGlvbnMgaW4gYSBkZWNs
YXJhdGl2ZSBBUEksIGhpZGluZyB0aGUgYm9pbGVycGxhdGUgY2FudmFzIGNvZGUuPGJyPjxicj48
L2Rpdj48ZGl2PlRoZSBBUEkgbWltaWNzIHRoZSBvbmUgcHJvdmlkZWQgYnkgZ2xvc3MgKGBQaWN0
dXJlYCwgYGFuaW1hdGVgLCBgcGxheWAuLi4pLCBidXQgc29tZSB0eXBlcyBhcmUgZGlmZmVyZW50
IHRvIGJldHRlciBhZGFwdCB0byBqcyBjb2RlIChleC4gaW1hZ2VzLCBmb250cywgaW5wdXRzKS48
YnI+PGJyPjwvZGl2PjxkaXY+RXhhbXBsZTombmJzcDsgPGJyPmBgYDxicj5tYWluID0gcnVuV2Vi
R1VJICQgXCB3ZWJWaWV3IC0mZ3Q7IGRvPGJyPiZuYnNwOyZuYnNwOyZuYnNwOyBjdHggJmx0Oy0g
Zml4ZWRTaXplQ2FudmFzIHdlYlZpZXcgODAwIDYwMDxicj4mbmJzcDsmbmJzcDsmbmJzcDsgbGV0
IGNvbmNlbnRyaWNDaXJjbGVzID0gZm9sZE1hcCBDaXJjbGUgWzEsMTAuLjEwMF08YnI+Jm5ic3A7
Jm5ic3A7Jm5ic3A7IGRyYXcgY3R4IGNvbmNlbnRyaWNDaXJjbGVzIC0tIG9uZS1zaG90IGRyYXdp
bmc8YnI+YGBgPGJyPjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+VGhlIG9ubHkgZGlyZWN0IGRl
cGVuZGVuY3kgaXMgZ2hjanMtZG9tLCBzbyB0aGUgcmVzdWx0aW5nIGpzZXhlIHNob3VsZCBiZSBy
ZWxhdGl2ZWx5IGxpZ2h0d2VpZ2h0Ljxicj48YnI+PC9kaXY+PGRpdj5JIGFsc28gd3JvdGUgc2hp
bmUtdmFyeWluZywgYSBGUlAgaW50ZXJmYWNlIHRvIHNoaW5lIGluIHRlcm1zIG9mIFZhcnMgcGx1
cyBzb21lIHV0aWxpdHkgVmFycy48YnI+PGJyPjwvZGl2PjxkaXY+RXhhbXBsZSAodHJhbnNsYXRp
b24gb2YgdGhlIHJlc2l6ZS15b2dpIEVsbSBleGFtcGxlKTombmJzcDsgPGJyPjwvZGl2PjxkaXY+
YGBgPGJyPnJlc2l6ZUltYWdlIGltZyAoeCcseScpID0gVHJhbnNsYXRlICh4LzIpICh5LzIpIC0t
IFBpY3R1cmVzIGFyZSBjZW50ZXJlZCBvbiAoMCwwKSwgc28gd2UgbmVlZCB0byBtb3ZlIGl0PGJy
PiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZu
YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNw
OyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyAkIEltYWdlIChTdHJldGNoZWQgeCB5KSBpbWcgLS0g
U2NhbGUgdGhlIHBpY3R1cmUgdG8gdGhlIGdpdmVuIHBvc2l0aW9uPGJyPiZuYnNwOyB3aGVyZTxi
cj4mbmJzcDsmbmJzcDsmbmJzcDsgeCA9IGZyb21JbnRlZ3JhbCB4JyAtLSBtb3VzZVBvc2l0aW9u
IGlzIEludGVncmFsPGJyPiZuYnNwOyZuYnNwOyZuYnNwOyB5ID0gZnJvbUludGVncmFsIHknPGJy
Pjxicj5tYWluID0gcnVuV2ViR1VJICQgXCB3ZWJWaWV3IC0mZ3Q7IGRvPGJyPiZuYnNwOyZuYnNw
OyZuYnNwOyBjdHggJmx0Oy0gZml4ZWRTaXplQ2FudmFzIHdlYlZpZXcgMTAyNCA3Njg8YnI+Jm5i
c3A7Jm5ic3A7Jm5ic3A7IEp1c3QgZG9jICZsdDstIHdlYlZpZXdHZXREb21Eb2N1bWVudCB3ZWJW
aWV3PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyBuYXJ3aGFsICZsdDstIG1ha2VJbWFnZSAiaHR0cHM6
Ly93aWtpLmhhc2tlbGwub3JnL3dpa2l1cGxvYWQvOC84NS9OYXJsZXlZZWVhYWFoaC5qcGciPGJy
PiZuYnNwOyZuYnNwOyZuYnNwOyBsZXQgcmVzaXplZE5hcndoYWwgPSByZXNpemVJbWFnZSBuYXJ3
aGFsICZsdDskJmd0OyBtb3VzZVBvc2l0aW9uPGJyPiZuYnNwOyZuYnNwOyZuYnNwOyBwbGF5VmFy
eWluZyBjdHggZG9jIDMwIHJlc2l6ZWROYXJ3aGFsPGJyPmBgYDxicj48YnI+PC9kaXY+PGRpdj5J
IHBsYW4gdG8gd3JpdGUvcG9ydCBhIGZldyBzaW1wbGUgZ2FtZXMgd2l0aCBpdCBzb29uLjxicj48
YnI+PC9kaXY+RnJhbmNlc2NvPGJyPg==" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0">​</div></div></div>