Skip to content
This repository was archived by the owner on Jul 19, 2022. It is now read-only.

Commit e186e44

Browse files
authored
Merge pull request #298 from unisonweb/hashvatars
Add Hashvatars
2 parents 76bb32c + abebe9d commit e186e44

File tree

15 files changed

+905
-20
lines changed

15 files changed

+905
-20
lines changed

elm.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"dependencies": {
88
"direct": {
99
"NoRedInk/elm-simple-fuzzy": "1.0.3",
10+
"avh4/elm-color": "1.0.0",
1011
"elm/browser": "1.0.2",
1112
"elm/core": "1.0.5",
1213
"elm/html": "1.0.0",
@@ -24,6 +25,7 @@
2425
"j-maas/elm-ordered-containers": "1.0.0",
2526
"krisajenkins/remotedata": "6.0.1",
2627
"mgold/elm-nonempty-list": "4.1.0",
28+
"noahzgordon/elm-color-extra": "1.0.2",
2729
"stoeffel/set-extra": "1.2.3",
2830
"wernerdegroot/listzipper": "4.0.0"
2931
},
@@ -33,12 +35,14 @@
3335
"elm/random": "1.0.0",
3436
"elm/time": "1.0.0",
3537
"elm/virtual-dom": "1.0.2",
38+
"fredcy/elm-parseint": "2.0.1",
3639
"rtfeldman/elm-iso8601-date-strings": "1.1.3"
3740
}
3841
},
3942
"test-dependencies": {
4043
"direct": {
41-
"elm-explorations/test": "1.2.2"
44+
"elm-explorations/test": "1.2.2",
45+
"TSFoster/elm-tuple-extra": "2.0.0"
4246
},
4347
"indirect": {}
4448
}

src/Color/Harmony.elm

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
module Color.Harmony exposing (..)
2+
3+
import Color exposing (Color)
4+
import List.Extra as ListE
5+
6+
7+
harmonizesWith : Color -> List Color
8+
harmonizesWith color =
9+
let
10+
complementary_ =
11+
complementary color
12+
13+
( analogousA, analogousB ) =
14+
analogous color
15+
16+
( triadicA, triadicB ) =
17+
triadic color
18+
19+
( splitA, splitB ) =
20+
splitComplementary color
21+
22+
( squareA, squareB, squareC ) =
23+
square color
24+
25+
( tetridicA, tetridicB, tetridicC ) =
26+
tetridic color
27+
28+
harmonizesWith_ =
29+
[ complementary_
30+
, analogousA
31+
, analogousB
32+
, triadicA
33+
, triadicB
34+
, splitA
35+
, splitB
36+
, squareA
37+
, squareB
38+
, squareC
39+
, tetridicA
40+
, tetridicB
41+
, tetridicC
42+
]
43+
in
44+
ListE.uniqueBy Color.toCssString harmonizesWith_
45+
46+
47+
{-| RGB Difference <https://en.wikipedia.org/wiki/Color_difference> - alpha is disregarded
48+
-}
49+
difference : Color -> Color -> Float
50+
difference a b =
51+
let
52+
a_ =
53+
toRgb255 a
54+
55+
b_ =
56+
toRgb255 b
57+
58+
sum =
59+
toFloat (((a_.red - b_.red) ^ 2) + ((a_.blue - b_.blue) ^ 2) + ((a_.green - b_.green) ^ 2))
60+
in
61+
sqrt sum
62+
63+
64+
toRgb255 : Color -> { red : Int, green : Int, blue : Int }
65+
toRgb255 c =
66+
let
67+
rgba =
68+
Color.toRgba c
69+
in
70+
{ red = floor (rgba.red * 255)
71+
, green = floor (rgba.red * 255)
72+
, blue = floor (rgba.blue * 255)
73+
}
74+
75+
76+
{-| Opposites on the color wheel
77+
-}
78+
complementary : Color -> Color
79+
complementary color =
80+
hueAdd 180 color
81+
82+
83+
{-| Adjacent colors on the color wheel
84+
-}
85+
analogous : Color -> ( Color, Color )
86+
analogous color =
87+
( hueAdd 30 color
88+
, hueSubtract 30 color
89+
)
90+
91+
92+
triadic : Color -> ( Color, Color )
93+
triadic color =
94+
( hueAdd 120 color
95+
, hueAdd 240 color
96+
)
97+
98+
99+
splitComplementary : Color -> ( Color, Color )
100+
splitComplementary color =
101+
( hueAdd 150 color
102+
, hueAdd 210 color
103+
)
104+
105+
106+
square : Color -> ( Color, Color, Color )
107+
square color =
108+
( hueAdd 90 color
109+
, hueAdd 180 color
110+
, hueAdd 270 color
111+
)
112+
113+
114+
tetridic : Color -> ( Color, Color, Color )
115+
tetridic color =
116+
( hueAdd 60 color
117+
, hueAdd 180 color
118+
, hueAdd 240 color
119+
)
120+
121+
122+
123+
-- Internal Helpers
124+
125+
126+
hueAdd : Int -> Color -> Color
127+
hueAdd num color =
128+
let
129+
hsla =
130+
Color.toHsla color
131+
132+
hue =
133+
hsla.hue
134+
|> toAngle
135+
|> (+) num
136+
|> wrap360
137+
|> toPt
138+
in
139+
Color.fromHsla { hsla | hue = hue }
140+
141+
142+
hueSubtract : Int -> Color -> Color
143+
hueSubtract num color =
144+
let
145+
hsla =
146+
Color.toHsla color
147+
148+
hue =
149+
hsla.hue
150+
|> toAngle
151+
|> (-) num
152+
|> wrap360
153+
|> toPt
154+
in
155+
Color.fromHsla { hsla | hue = hue }
156+
157+
158+
toAngle : Float -> Int
159+
toAngle pt =
160+
let
161+
a =
162+
floor (pt * 360)
163+
in
164+
if a > 360 then
165+
360 - (360 - a)
166+
167+
else
168+
a
169+
170+
171+
toPt : Int -> Float
172+
toPt ang =
173+
toFloat ang / 360
174+
175+
176+
wrap360 : Int -> Int
177+
wrap360 h =
178+
let
179+
x =
180+
modBy 360 h
181+
in
182+
if x < 0 then
183+
x + 360
184+
185+
else
186+
x

src/Hashvatar.elm

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
module Hashvatar exposing (..)
2+
3+
import Hash exposing (Hash)
4+
import Hashvatar.HexGrid as HexGrid
5+
import Html exposing (Html, div)
6+
import Html.Attributes exposing (class)
7+
import List.Extra as ListE
8+
import String.Extra exposing (break)
9+
import UI.Color as Color exposing (Color)
10+
11+
12+
view : Hash -> Html msg
13+
view hash =
14+
let
15+
raw =
16+
hash |> Hash.toString |> String.replace "#" ""
17+
18+
numSlots =
19+
5
20+
21+
partLength =
22+
String.length raw // numSlots
23+
24+
parts =
25+
break partLength raw
26+
27+
toCharCodeSum str =
28+
str
29+
|> String.toList
30+
|> List.foldl (\c acc -> acc + Char.toCode c) 0
31+
32+
grid =
33+
parts
34+
|> List.map toCharCodeSum
35+
|> toGrid
36+
|> Maybe.withDefault HexGrid.empty
37+
in
38+
div [ class "hashvatar" ]
39+
[ HexGrid.view grid
40+
]
41+
42+
43+
44+
-- Helpers
45+
46+
47+
getIn : Int -> List Color -> Maybe Color
48+
getIn unmoddedIdx colors_ =
49+
ListE.getAt (modBy (List.length colors_) unmoddedIdx) colors_
50+
51+
52+
toGrid : List Int -> Maybe HexGrid.HexGrid
53+
toGrid slots =
54+
let
55+
selectBg grid_ =
56+
let
57+
background =
58+
getIn grid_.background Color.darkNonGrays
59+
in
60+
Maybe.map
61+
(\bg ->
62+
{ background = bg
63+
, tendrils = grid_.tendrils
64+
, cell1 = grid_.cell1
65+
, cell2 = grid_.cell2
66+
, cell3 = grid_.cell3
67+
}
68+
)
69+
background
70+
71+
selectTendrils grid_ =
72+
let
73+
tendrils =
74+
getIn grid_.tendrils (Color.harmonizesWith grid_.background)
75+
in
76+
Maybe.map
77+
(\tr ->
78+
{ background = grid_.background
79+
, tendrils = tr
80+
, cell1 = grid_.cell1
81+
, cell2 = grid_.cell2
82+
, cell3 = grid_.cell3
83+
}
84+
)
85+
tendrils
86+
87+
selectCells grid_ =
88+
Maybe.map3
89+
(\cell1 cell2 cell3 ->
90+
{ background = grid_.background
91+
, tendrils = grid_.tendrils
92+
, cell1 = cell1
93+
, cell2 = cell2
94+
, cell3 = cell3
95+
}
96+
)
97+
(getIn grid_.cell1 (Color.harmonizesWith grid_.background))
98+
(getIn grid_.cell2 (Color.harmonizesWith grid_.background))
99+
(getIn grid_.cell3 (Color.harmonizesWith grid_.background))
100+
in
101+
Maybe.map5
102+
(\background tendrils cell1 cell2 cell3 ->
103+
{ background = background
104+
, tendrils = tendrils
105+
, cell1 = cell1
106+
, cell2 = cell2
107+
, cell3 = cell3
108+
}
109+
)
110+
(ListE.getAt 0 slots)
111+
(ListE.getAt 1 slots)
112+
(ListE.getAt 2 slots)
113+
(ListE.getAt 3 slots)
114+
(ListE.getAt 4 slots)
115+
|> Maybe.andThen selectBg
116+
|> Maybe.andThen selectTendrils
117+
|> Maybe.andThen selectCells

0 commit comments

Comments
 (0)