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