Shine은 자바스크립트의 그리기 기능을 선언적 API로 래핑합니다.
광택에서 많은 영감을 받았습니다.
여기에 데모 (컴파일된 샤인 예제)가 있습니다.
GHCJ가 필요해요
GHCJ 패키지를 구축하는 가장 좋은 방법은 반사 플랫폼을 사용하는 것입니다.
Picture
그림을 표현하려면 Picture
데이터 유형을 사용하여 트리를 만들어야 합니다.
pic :: Picture
pic = Rect 10 20 -- represents a 10x20 square
여러 개의 Picture
를 구성하려면 두 개의 Picture
를 받아 겹치는 Over
사용할 수 있습니다.
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
Graphics.Shine.Render
의 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 (코멘트)