يقوم Shine بتغليف وظائف الرسم في جافا سكريبت في واجهة برمجة التطبيقات التعريفية.
مستوحاة بشدة من اللمعان.
العرض التوضيحي (أمثلة التألق المجمعة) هنا
أنت بحاجة إلى ghcjs
إحدى الطرق الرائعة لبناء حزم ghcjs هي استخدام المنصة الانعكاسية
Picture
ق لتمثيل الرسم الخاص بك، عليك إنشاء شجرة باستخدام نوع بيانات Picture
.
pic :: Picture
pic = Rect 10 20 -- represents a 10x20 square
لإنشاء Picture
متعددة، يمكنك استخدام Over
، الذي يقبل Picture
ويتداخل معهما.
Picture
أحادية: <>
هو اسم مستعار لـ Over
و mempty
هي الصورة الفارغة.
-- 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. "
باستخدام Foldable
يمكنك القيام بأشياء مثل
concentricCircles :: Picture
concentricCircles = foldMap Circle [ 1 , 10 .. 100 ]
Picture
ق قبل رسم أي شيء، تحتاج إلى الحصول على CanvasRenderingContext2D
(وأحيانًا Document
). ولهذا الغرض، يوفر Shine وظيفتين مفيدتين: fullScreenCanvas
و 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)
لتقديم Picture
في سياق لديك ثلاثة خيارات:
render
يمكنك رسمه يدويًا باستخدام render
من Graphics.Shine.Render
main :: IO ()
{- omitted: get the context, see before -}
render ctx concentricCircles
animate
يمكنك رسم Picture
تعتمد على الوقت. وهذا هو، 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
وأخيرًا، يمكنك رسم Picture
تعتمد على الوقت والمدخلات (لوحة المفاتيح والماوس) والحالة الداخلية. وهذا مفيد بشكل خاص للألعاب، ومن هنا جاء الاسم.
-- 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
انظر حزمة shine-examples
(Hackage).
يعد التعامل مع الأصول باستخدام ghcjs والمتصفح أمرًا صعبًا إلى حد ما.
الطريقة المعتادة للقيام بذلك مع برامج هاسكل العادية هي استخدام data-files
. لسوء الحظ، يعمل هذا إما عن طريق تشفير المسار المطلق في الملف القابل للتنفيذ، والذي لن يعمل عندما يتم وضع البرنامج على خادم في مسار مختلف، أو عن طريق تجاوز متغير البيئة ( $pkgname_datadir
)، والذي لن يعمل لأن متغيرات البيئة تعمل غير موجود في المتصفح.
لذا، في الوقت الحالي، يتمثل الحل في تحديد المسارات المطلقة أو النسبية بشكل صريح في الكود المصدري، ثم نسخ الأصول بشكل متكرر إلى الموقع المناسب بعد إنشاء/نشر الكود. وهذا ما فعلته في العرض التوضيحي animated-shapes
لصورة الفلفل.
تذكرة عصابة ذات صلة، تناقش طريقة جديدة محتملة للتعامل مع الأصول: haskell/cabal#6096 (تعليق)