on bb9ffcf help sign in
elk/libraries/Color.elm
272 lines 8.1 kB history raw
1module Color where
3{-| Library for working with colors. Includes
4[RGB](https://en.wikipedia.org/wiki/RGB_color_model) and
5[HSL](http://en.wikipedia.org/wiki/HSL_and_HSV) creation, gradients, and
6built-in names.
8# Creation
9@docs rgb, rgba, hsl, hsla, greyscale, grayscale, complement
11# Gradients
12@docs linear, radial
14# Extracting Colors
15@docs toRgb, toHsl
17# Built-in Colors
18These colors come from the [Tango
19palette](http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines)
20which provides aesthetically reasonable defaults for colors. Each color also
21comes with a light and dark version.
23### Standard
24@docs red, orange, yellow, green, blue, purple, brown
26### Light
27@docs lightRed, lightOrange, lightYellow, lightGreen, lightBlue, lightPurple, lightBrown
29### Dark
30@docs darkRed, darkOrange, darkYellow, darkGreen, darkBlue, darkPurple, darkBrown
32### Eight Shades of Grey
33These colors are a compatible series of shades of grey, fitting nicely
34with the Tango palette.
35@docs white, lightGrey, grey, darkGrey, lightCharcoal, charcoal, darkCharcoal, black
37These are identical to the *grey* versions. It seems the spelling is regional, but
38that has never helped me remember which one I should be writing.
39@docs lightGray, gray, darkGray
41-}
43import Basics (..)
45data Color
46 = RGBA Int Int Int Float
47 | HSLA Float Float Float Float
49{-| Create RGB colors with an alpha component for transparency.
50The alpha component is specified with numbers between 0 and 1. -}
51rgba : Int -> Int -> Int -> Float -> Color
52rgba = RGBA
54{-| Create RGB colors from numbers between 0 and 255 inclusive. -}
55rgb : Int -> Int -> Int -> Color
56rgb r g b = RGBA r g b 1
58{-| Create [HSL colors](http://en.wikipedia.org/wiki/HSL_and_HSV)
59with an alpha component for transparency.
60-}
61hsla : Float -> Float -> Float -> Float -> Color
62hsla hue saturation lightness alpha =
63 HSLA (hue - turns (toFloat (floor (hue / (2*pi))))) saturation lightness alpha
65{-| Create [HSL colors](http://en.wikipedia.org/wiki/HSL_and_HSV). This gives
66you access to colors more like a color wheel, where all hues are aranged in a
67circle that you specify with standard Elm angles (radians).
69 red = hsl (degrees 0) 1 0.5
70 green = hsl (degrees 120) 1 0.5
71 blue = hsl (degrees 240) 1 0.5
73 pastelRed = hsl (degrees 0) 0.7 0.7
75To cycle through all colors, just cycle through degrees. The saturation level
76is how vibrant the color is, like a dial between grey and bright colors. The
77lightness level is a dial between white and black.
78-}
79hsl : Float -> Float -> Float -> Color
80hsl hue saturation lightness =
81 hsla hue saturation lightness 1
83{-| Produce a gray based on the input. 0 is white, 1 is black. -}
84grayscale : Float -> Color
85grayscale p = HSLA 0 0 (1-p) 1
87greyscale : Float -> Color
88greyscale p = HSLA 0 0 (1-p) 1
90{-| Produce a “complementary color”. The two colors will
91accent each other. This is the same as rotating the hue by 180°.
92-}
93complement : Color -> Color
94complement color =
95 case color of
96 HSLA h s l a -> hsla (h + degrees 180) s l a
97 RGBA r g b a -> let (h,s,l) = rgbToHsl r g b
98 in hsla (h + degrees 180) s l a
100{-| Extract the components of a color in the HSL format.
101-}
102toHsl : Color -> { hue:Float, saturation:Float, lightness:Float, alpha:Float }
103toHsl color =
104 case color of
105 HSLA h s l a -> { hue=h, saturation=s, lightness=l, alpha=a }
106 RGBA r g b a ->
107 let (h,s,l) = rgbToHsl r g b
108 in { hue=h, saturation=s, lightness=l, alpha=a }
110{-| Extract the components of a color in the RGB format.
111-}
112toRgb : Color -> { red:Int, green:Int, blue:Int, alpha:Float }
113toRgb color =
114 case color of
115 RGBA r g b a -> { red=r, green=g, blue=b, alpha=a }
116 HSLA h s l a ->
117 let (r,g,b) = hslToRgb h s l
118 in { red = round (255 * r)
119 , green = round (255 * g)
120 , blue = round (255 * b)
121 , alpha = a
122 }
124fmod : Float -> Int -> Float
125fmod f n =
126 let integer = floor f
127 in toFloat (integer `mod` n) + f - toFloat integer
129rgbToHsl : Int -> Int -> Int -> (Float,Float,Float)
130rgbToHsl red green blue =
131 let r = toFloat red / 255
132 g = toFloat green / 255
133 b = toFloat blue / 255
135 cMax = max (max r g) b
136 cMin = min (min r g) b
138 c = cMax - cMin
140 hue = degrees 60 * if | cMax == r -> ((g - b) / c) `fmod` 6
141 | cMax == g -> ((b - r) / c) + 2
142 | cMax == b -> ((r - g) / c) + 4
144 lightness = (cMax + cMin) / 2
146 saturation =
147 if lightness == 0
148 then 0
149 else c / (1 - abs (2 * lightness - 1))
150 in
151 (hue, saturation, lightness)
153hslToRgb : Float -> Float -> Float -> (Float,Float,Float)
154hslToRgb hue saturation lightness =
155 let chroma = (1 - abs (2 * lightness - 1)) * saturation
156 hue' = hue / degrees 60
158 x = chroma * (1 - abs (fmod hue' 2 - 1))
160 (r,g,b) = if | hue' < 0 -> (0, 0, 0)
161 | hue' < 1 -> (chroma, x, 0)
162 | hue' < 2 -> (x, chroma, 0)
163 | hue' < 3 -> (0, chroma, x)
164 | hue' < 4 -> (0, x, chroma)
165 | hue' < 5 -> (x, 0, chroma)
166 | hue' < 6 -> (chroma, 0, x)
167 | otherwise -> (0, 0, 0)
169 m = lightness - chroma / 2
170 in
171 (r + m, g + m, b + m)
173--toV3 : Color -> V3
175--toV4 : Color -> V4
177data Gradient
178 = Linear (Float,Float) (Float,Float) [(Float,Color)]
179 | Radial (Float,Float) Float (Float,Float) Float [(Float,Color)]
181{-| Create a linear gradient. Takes a start and end point and then a series of
182&ldquo;color stops&rdquo; that indicate how to interpolate between the start and
183end points. See [this example](/edit/examples/Elements/LinearGradient.elm) for a
184more visual explanation. -}
185linear : (number, number) -> (number, number) -> [(Float,Color)] -> Gradient
186linear = Linear
188{-| Create a radial gradient. First takes a start point and inner radius. Then
189takes an end point and outer radius. It then takes a series of &ldquo;color
190stops&rdquo; that indicate how to interpolate between the inner and outer
191circles. See [this example](/edit/examples/Elements/RadialGradient.elm) for a
192more visual explanation. -}
193radial : (number,number) -> number -> (number,number) -> number -> [(Float,Color)] -> Gradient
194radial = Radial
197-- BUILT-IN COLORS
199lightRed : Color
200lightRed = RGBA 239 41 41 1
201red : Color
202red = RGBA 204 0 0 1
203darkRed : Color
204darkRed = RGBA 164 0 0 1
206lightOrange : Color
207lightOrange = RGBA 252 175 62 1
208orange : Color
209orange = RGBA 245 121 0 1
210darkOrange : Color
211darkOrange = RGBA 206 92 0 1
213lightYellow : Color
214lightYellow = RGBA 255 233 79 1
215yellow : Color
216yellow = RGBA 237 212 0 1
217darkYellow : Color
218darkYellow = RGBA 196 160 0 1
220lightGreen : Color
221lightGreen = RGBA 138 226 52 1
222green : Color
223green = RGBA 115 210 22 1
224darkGreen : Color
225darkGreen = RGBA 78 154 6 1
227lightBlue : Color
228lightBlue = RGBA 114 159 207 1
229blue : Color
230blue = RGBA 52 101 164 1
231darkBlue : Color
232darkBlue = RGBA 32 74 135 1
234lightPurple : Color
235lightPurple = RGBA 173 127 168 1
236purple : Color
237purple = RGBA 117 80 123 1
238darkPurple : Color
239darkPurple = RGBA 92 53 102 1
241lightBrown : Color
242lightBrown = RGBA 233 185 110 1
243brown : Color
244brown = RGBA 193 125 17 1
245darkBrown : Color
246darkBrown = RGBA 143 89 2 1
248black : Color
249black = RGBA 0 0 0 1
250white : Color
251white = RGBA 255 255 255 1
253lightGrey : Color
254lightGrey = RGBA 238 238 236 1
255grey : Color
256grey = RGBA 211 215 207 1
257darkGrey : Color
258darkGrey = RGBA 186 189 182 1
260lightGray : Color
261lightGray = RGBA 238 238 236 1
262gray : Color
263gray = RGBA 211 215 207 1
264darkGray : Color
265darkGray = RGBA 186 189 182 1
267lightCharcoal : Color
268lightCharcoal = RGBA 136 138 133 1
269charcoal : Color
270charcoal = RGBA 85 87 83 1
271darkCharcoal : Color
272darkCharcoal = RGBA 46 52 54 1