on eb2a032 help sign in
elk/libraries/Graphics/Collage.elm
216 lines 6.6 kB history raw
2module Graphics.Collage where
4import open Basics
5import List
6import Either (Either, Left, Right)
7import Transform2D (Transform2D, identity)
8import Native.Graphics.Collage
9import Graphics.Element (Element)
10import Color (Color, black, Gradient)
11import Maybe (Maybe)
12import JavaScript (JSString)
14type Form = {
15 theta : Float,
16 scale : Float,
17 x : Float,
18 y : Float,
19 alpha : Float,
20 form : BasicForm
21 }
23data FillStyle
24 = Solid Color
25 | Texture String
26 | Grad Gradient
28-- The shape of the ends of a line.
29data LineCap = Flat | Round | Padded
31-- The shape of the “joints” of a line, where each line segment
32-- meets. `Sharp` takes an argument to limit the length of the joint. This
33-- defaults to 10.
34data LineJoin = Smooth | Sharp Float | Clipped
36-- All of the attributes of a line style. This lets you build up a line style
37-- however you want. You can also update existing line styles with record updates.
38type LineStyle = {
39 color : Color,
40 width : Float,
41 cap : LineCap,
42 join : LineJoin,
43 dashing : [Int],
44 dashOffset : Int
45 }
47-- The default line style, which is solid black with flat caps and sharp joints.
48-- You can use record updates to build the line style you
49-- want. For example, to make a thicker line, you could say:
50--
51-- { defaultLine | width <- 10 }
52defaultLine : LineStyle
53defaultLine = {
54 color = black,
55 width = 1,
56 cap = Flat,
57 join = Sharp 10,
58 dashing = [],
59 dashOffset = 0
60 }
62-- Create a solid line style with a given color.
63solid : Color -> LineStyle
64solid clr = { defaultLine | color <- clr }
66-- Create a dashed line style with a given color. Dashing equals `[8,4]`.
67dashed : Color -> LineStyle
68dashed clr = { defaultLine | color <- clr, dashing <- [8,4] }
70-- Create a dotted line style with a given color. Dashing equals `[3,3]`.
71dotted : Color -> LineStyle
72dotted clr = { defaultLine | color <- clr, dashing <- [3,3] }
74data BasicForm
75 = FPath LineStyle Path
76 | FShape (Either LineStyle FillStyle) Shape
77 | FImage Int Int (Int,Int) String
78 | FElement Element
79 | FGroup Transform2D [Form]
81form : BasicForm -> Form
82form f = { theta=0, scale=1, x=0, y=0, alpha=1, form=f }
84fill style shape = form (FShape (Right style) shape)
86-- Create a filled in shape.
87filled : Color -> Shape -> Form
88filled color shape = fill (Solid color) shape
90-- Create a textured shape. The texture is described by some url and is
91-- tiled to fill the entire shape.
92textured : String -> Shape -> Form
93textured src shape = fill (Texture src) shape
95-- Fill a shape with a [gradient](/docs/Color.elm#linear).
96gradient : Gradient -> Shape -> Form
97gradient grad shape = fill (Grad grad) shape
99-- Outline a shape with a given line style.
100outlined : LineStyle -> Shape -> Form
101outlined style shape = form (FShape (Left style) shape)
103-- Trace a path with a given line style.
104traced : LineStyle -> Path -> Form
105traced style path = form (FPath style path)
107-- Create a sprite from a sprite sheet. It cuts out a rectangle
108-- at a given position.
109sprite : Int -> Int -> (Int,Int) -> String -> Form
110sprite w h pos src = form (FImage w h pos src)
112-- Turn any `Element` into a `Form`. This lets you use text, gifs, and video
113-- in your collage. This means you can move, rotate, and scale
114-- an `Element` however you want.
115toForm : Element -> Form
116toForm e = form (FElement e)
118-- Flatten many forms into a single `Form`. This lets you move and rotate them
119-- as a single unit, making it possible to build small, modular components.
120group : [Form] -> Form
121group fs = form (FGroup identity fs)
123-- Flatten many forms into a single `Form` and then apply a matrix
124-- transformation.
125groupTransform : Transform2D -> [Form] -> Form
126groupTransform matrix fs = form (FGroup matrix fs)
128-- Rotate a form by a given angle. Rotate takes standard Elm angles (radians)
129-- and turns things counterclockwise. So to turn `form` 30&deg; to the left
130-- you would say, `(rotate (degrees 30) form)`.
131rotate : number -> Form -> Form
132rotate t f = { f | theta <- f.theta + t }
134-- Scale a form by a given factor. Scaling by 2 doubles the size.
135scale : number -> Form -> Form
136scale s f = { f | scale <- f.scale * s }
138-- Move a form by the given amount. This is a relative translation so
139-- `(move (10,10) form)` would move `form` ten pixels up and ten pixels to the
140-- right.
141move : (number,number) -> Form -> Form
142move (x,y) f = { f | x <- f.x + x, y <- f.y + y }
144-- Move a shape in the x direction. This is relative so `(moveX 10 form)` moves
145-- `form` 10 pixels to the right.
146moveX : number -> Form -> Form
147moveX x f = { f | x <- f.x + x }
149-- Move a shape in the y direction. This is relative so `(moveY 10 form)` moves
150-- `form` upwards by 10 pixels.
151moveY : number -> Form -> Form
152moveY y f = { f | y <- f.y + y }
154-- Set the alpha of a `Form`. The default is 1, and 0 is totally transparent.
155alpha : Float -> Form -> Form
156alpha a f = { f | alpha <- a }
158-- A collage is a collection of 2D forms. There are no strict positioning
159-- relationships between forms, so you are free to do all kinds of 2D graphics.
160collage : Int -> Int -> [Form] -> Element
161collage = Native.Graphics.Collage.collage
164type Path = [(number,number)]
166-- Create a path that follows a sequence of points.
167path : [(number,number)] -> Path
168path ps = ps
170-- Create a path along a given line segment.
171segment : (number,number) -> (number,number) -> Path
172segment p1 p2 = [p1,p2]
174type Shape = [(number,number)]
176-- Create an arbitrary polygon by specifying its corners in order.
177-- `polygon` will automatically close all shapes, so the given list
178-- of points does not need to start and end with the same position.
179polygon : [(number,number)] -> Shape
180polygon points = points
182-- A rectangle with a given width and height.
183rect : number -> number -> Shape
184rect w h = let hw = w/2
185 hh = h/2
186 in [ (0-hw,0-hh), (0-hw,hh), (hw,hh), (hw,0-hh) ]
188-- A square with a given edge length.
189square : number -> Shape
190square n = rect n n
192-- An oval with a given width and height.
193oval : number -> number -> Shape
194oval w h =
195 let n = 50
196 t = 2 * pi / n
197 hw = w/2
198 hh = h/2
199 f i = (hw * cos (t*i), hh * sin (t*i))
200 in List.map f [0..n-1]
202-- A circle with a given radius.
203circle : number -> Shape
204circle r = oval (2*r) (2*r)
206-- A regular polygon with N sides. The first argument specifies the number
207-- of sides and the second is the radius. So to create a pentagon with radius
208-- 30 you would say:
209--
210-- ngon 5 30
211ngon : Int -> number -> Shape
212ngon n r =
213 let m = toFloat n
214 t = 2 * pi / m
215 f i = ( r * cos (t*i), r * sin (t*i) )
216 in List.map f [0..m-1]