on da346ea help sign in
elk/libraries/Graphics/Collage.elm
214 lines 6.6 kB history raw
2module Graphics.Collage where
4import List
5import Basics (toFloat)
6import Either
7import Matrix2D as Matrix
8import Native.Graphics.Collage as Native
9import Graphics.Element (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
159collage = Native.collage
162type Path = [(Float,Float)]
164-- Create a path that follows a sequence of points.
165path : [(number,number)] -> Path
166path ps = ps
168-- Create a path along a given line segment.
169segment : (number,number) -> (number,number) -> Path
170segment p1 p2 = [p1,p2]
172type Shape = [(Float,Float)]
174-- Create an arbitrary polygon by specifying its corners in order.
175-- `polygon` will automatically close all shapes, so the given list
176-- of points does not need to start and end with the same position.
177polygon : [(number,number)] -> Shape
178polygon points = points
180-- A rectangle with a given width and height.
181rect : number -> number -> Shape
182rect w h = let hw = w/2
183 hh = h/2
184 in [ (0-hw,0-hh), (0-hw,hh), (hw,hh), (hw,0-hh) ]
186-- A square with a given edge length.
187square : number -> Shape
188square n = rect n n
190-- An oval with a given width and height.
191oval : number -> number -> Shape
192oval w h =
193 let n = 50
194 t = 2 * Math.PI / n
195 hw = w/2
196 hh = h/2
197 f i = (hw * Math.cos (t*i), hh * Math.sin (t*i))
198 in List.map f [0..n-1]
200-- A circle with a given radius.
201circle : number -> Shape
202circle r = oval (2*r) (2*r)
204-- A regular polygon with N sides. The first argument specifies the number
205-- of sides and the second is the radius. So to create a pentagon with radius
206-- 30 you would say:
207--
208-- ngon 5 30
209ngon : Int -> number -> Shape
210ngon n r =
211 let m = toFloat n
212 t = 2 * Math.PI / m
213 f i = ( r * Math.cos (t*i), r * Math.sin (t*i) )
214 in List.map f [0..n-1]