Shine membungkus fungsi menggambar javascript dalam API deklaratif.
Sangat terinspirasi oleh gloss.
demo (kompilasi contoh bersinar) di sini
Anda membutuhkan ghcj
Cara terbaik untuk membuat paket ghcjs adalah dengan menggunakan platform refleks
Picture
s Untuk merepresentasikan gambar Anda, Anda harus membuat pohon menggunakan tipe data Picture
.
pic :: Picture
pic = Rect 10 20 -- represents a 10x20 square
Untuk membuat beberapa Picture
, Anda dapat menggunakan Over
, yang menerima dua Picture
dan menumpuknya.
Picture
adalah monoid: <>
adalah alias untuk Over
dan mempty
adalah gambar kosong.
-- 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. "
Dengan menggunakan Foldable
Anda dapat melakukan hal-hal seperti
concentricCircles :: Picture
concentricCircles = foldMap Circle [ 1 , 10 .. 100 ]
Picture
s Sebelum menggambar apa pun, Anda perlu mendapatkan CanvasRenderingContext2D
(dan terkadang Document
). Untuk tujuan ini, bersinar menyediakan dua fungsi utilitas: fullScreenCanvas
dan fixedSizeCanvas
{-# LANGUAGE CPP #-}
import Graphics.Shine
import Graphics.Shine.Input
import Graphics.Shine.Picture
import GHCJS.DOM ( currentDocumentUnchecked )
-- This is how the ghcjs-dom hello-world does it.
-- It's boilerplate, so in the next shine version there
-- will probably be a ready-to-use run function
#if defined(ghcjs_HOST_OS)
run :: a -> a
run = id
#elif defined(MIN_VERSION_jsaddle_wkwebview)
import Language.Javascript.JSaddle.WKWebView ( run )
#else
import Language.Javascript.JSaddle.WebKitGTK ( run )
#endif
main :: IO ()
main = run $ do
doc <- currentDocumentUnchecked -- use currentDocument to handle failure
ctx <- fixedSizeCanvas doc 400 400
-- do something with ctx (and maybe doc)
Untuk merender Picture
pada suatu konteks, Anda memiliki tiga opsi:
render
Anda dapat menggambarnya secara manual menggunakan render
dari Graphics.Shine.Render
main :: IO ()
{- omitted: get the context, see before -}
render ctx concentricCircles
animate
Anda dapat menggambar Picture
yang bergantung pada waktu. Yaitu, 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 = do
{- omitted: get the context, see before -}
animate ctx 30 animation
play
Terakhir, Anda dapat menggambar Picture
yang bergantung pada waktu, input (keyboard dan mouse), dan keadaan internal. Ini sangat berguna untuk permainan, itulah namanya.
-- this code draws a black rectangle in the center of the canvas only when the
-- left mouse button is pressed
main :: IO ()
main = do
{- omitted: get the context and the document, see before -}
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
Lihat paket shine-examples
(Hackage).
Menangani aset dengan ghcjs dan browser agak rumit.
Cara yang biasa dilakukan untuk program haskell normal adalah dengan menggunakan data-files
. Sayangnya, ini berfungsi dengan melakukan hardcoding jalur absolut dalam executable, yang tidak akan berfungsi ketika program diletakkan di server di jalur yang berbeda, atau dengan penggantian variabel lingkungan ( $pkgname_datadir
), yang tidak akan berfungsi karena variabel lingkungan berfungsi tidak ada di browser.
Jadi, untuk saat ini, solusinya adalah dengan secara eksplisit menentukan jalur absolut atau relatif dalam kode sumber, dan kemudian menyalin aset ke lokasi yang sesuai setelah membuat/menerapkan kode. Inilah yang saya lakukan dalam demo animated-shapes
untuk gambar paprika.
Tiket komplotan rahasia yang relevan, mendiskusikan kemungkinan cara baru dalam menangani aset: haskell/cabal#6096 (komentar)