Commits: 1
Outline lines and gradients
index 936c34e..2daa781 100644
--- a/index.md
+++ b/index.md
@@ -20,7 +20,7 @@ presentation:
=
= - Atom
=
-
+Day 1
=
=- Setup the project
=
@@ -80,6 +80,8 @@ presentation:
= - Exercise: make 3 more dots (5 total)
=
=
+Day 2
+
=- Place the dots in a circle
=
= - Introduce a problem: We want to place the dots in a circle: show an example in the slides
@@ -116,6 +118,11 @@ presentation:
=
= Create a viewbox with correct perimeters (must be more than the radius of the circle plus the radius of a dot in each direction, and width and height are circumference)
=
+ ```elm
+ svg [ viewbox "-100 -100 200 200" ] []
+ ```
+
+Day 3
=
=- Let the computer do the math
=
@@ -349,8 +356,8 @@ presentation:
= ```elm
= dot angle color =
= circle
- [ cx (x 72)
- , cy (y 72)
+ [ cx (x angle)
+ , cy (y angle)
= , r "10"
= , fill color
= ]
@@ -362,10 +369,10 @@ presentation:
= ```
= svg [ viewbox "-100 -100 200 200" ]
= [ dot 0 "darkred"
- , dot 288 "gold"
= , dot 72 "fuchsia"
= , dot 144 "saddlebrown"
= , dot 216 "deepskyblue"
+ , dot 288 "gold"
= ]
= ```
=
@@ -375,11 +382,176 @@ presentation:
=
= - Show List and list operations (map and indexedMap)
=
+ There are a number of functions that operate on lists, for example `List.length` and `List.map`.
+
+ Examples of a map: a shopping list, after you find each item and place it in your basket, you are 'mapping' from a list of needed items to a list of items in your basket. Now you have two lists, and they are related. One is your original shopping list, the other the list of items in the basket.
+
+ Demonstrate:
+
+ ```elm
+ > things = ["Programming", "Swimming", "Dancing", "Saddle brown"]
+ ["Programming","Swimming","Dancing","Saddle brown"]
+ : List String
+
+
+ > List.length things
+ 4 : Int
+
+ > List.map fun things
+ ["Programming is fun!","Swimming is fun!","Dancing is fun!","Saddle brown is fun!"]
+ : List String
+
+ > things
+ ["Programming","Swimming","Dancing","Saddle brown"]
+ : List String
+ ```
+
+ Notice our original `things` list is unchanged. This is different from our rubber duck machine. The rubber duck turns the plastic and paint into rubber ducks. A function on the other hand 'creates' the value it gives you. You don't loose the original value given to it.
+
= - Make a `palette : List color`
=
+ ```elm
+ palette =
+ [ "darkred"
+ , "fuchsia"
+ , "saddlebrown"
+ , "deepskyblue"
+ , "gold"
+ ]
+ ```
+
= - Use `List.indexedMap dot palette` to generate the dots
=
+ Another function that operates on lists is `List.indexedMap`. Let's see it at work:
=
+ ```elm
+ dot index color =
+ circle
+ [ cx (x ((360 / (List.length palette)) * index))
+ , cy (y ((360 / (List.length palette)) * index))
+ , r "10"
+ , fill color
+ ]
+
+ List.indexedMap dot palette
+ ```
+
+ We can introduce a `let` block to make our code more readable and avoid repetition.
+
+ ```elm
+ dot index color =
+ let
+ angle =
+ (360 / count) * index
+
+ count =
+ List.length palette
+ in
+ circle
+ [ cx (x angle)
+ , cy (y angle)
+ , r "10"
+ , fill color
+ ]
+ ```
+
+ Take a look at the [documentation for `List.indexedMap`](https://package.elm-lang.org/packages/elm/core/latest/List#indexedMap).
+
+
+Day 4
+
+Introduce SVG groups
+
+ - We'll need one group for the dots and one group for the lines
+
+ ```elm
+ svg [ viewBox "-100 -100 200 200" ]
+ [ Svg.g [] (List.indexedMap dot pallete)
+ , Svg.g [] [ Svg.line [ x1 "123", y1 "112", x2 "41", y2 "11", stroke "black" ] [] ]
+ ]
+ ```
+
+ Exercise: add a few lines with different colors
+
+ Now we'll learn how to color a line with a gradient (going from one color to another)
+
+ ```
+ svg [ width "600", height "600", viewBox "-300 -300 600 600" ]
+ [ Svg.g [] (List.indexedMap dot pallete)
+ , Svg.defs []
+ [ Svg.linearGradient [ Svg.Attributes.id "MyGradient", x1 "0", y1 "0", x2 "1", y2 "0" ]
+ [ Svg.stop [ Svg.Attributes.offset "0", Svg.Attributes.stopColor "saddlebrown" ] []
+ , Svg.stop [ Svg.Attributes.offset "1", Svg.Attributes.stopColor "pink" ] []
+ ]
+ ]
+ , Svg.g []
+ [ Svg.line [ x1 "0", y1 "0", x2 "100", y2 "100", stroke "url(#MyGradient)" ] []
+ , Svg.line [ x1 "0", y1 "0", x2 "-100", y2 "-100", stroke "url(#MyGradient)" ] []
+ ]
+ ]
+ ```
+
+ We see a problem here. The gradient always goes from saddlebrown to pink from top left to bottom right. If we want to use the same gradient to connect different points, we'll need to be creative.
+
+ ```
+ main =
+ svg [ width "600", height "600", viewBox "-300 -300 600 600" ]
+ [ Svg.g [] (List.indexedMap dot pallete)
+ , Svg.defs []
+ [ Svg.linearGradient [ Svg.Attributes.id "MyGradient", x1 "0", y1 "0", x2 "1", y2 "0", gradientUnits "userSpaceOnUse" ]
+ [ Svg.stop [ Svg.Attributes.offset "0", Svg.Attributes.stopColor "saddlebrown" ] []
+ , Svg.stop [ Svg.Attributes.offset "1", Svg.Attributes.stopColor "pink" ] []
+ ]
+ ]
+ , Svg.g []
+ [ Svg.line [ x1 "0", y1 "0", x2 "1", y2 "0", transform "rotate(45),scale(100,1)", stroke "url(#MyGradient)" ] []
+ , Svg.line [ x1 "0", y1 "0", x2 "1", y2 "0", transform "rotate(180),scale(100,1)", stroke "url(#MyGradient)" ] []
+ , Svg.line [ x1 "0", y1 "0", x2 "1", y2 "0", transform "rotate(270),scale(100,1)", stroke "url(#MyGradient)" ] []
+ ]
+ ]
+ ```
+
+ We need to fix the viewbox!
+
+ Here's the trick: we have the lines initially match the gradient. We're using the same x and y values for all the lines and the gradient. Then we transform the lines to position them where we'd like them. We're actually using our old friend polar coordinates here.
+
+ If you're interested in what `gradientUnits "userSpaceOnUse"` does, come see me after the lesson.
+
+ ```elm
+ gradient : Int -> String -> Svg msg
+ gradient index color =
+ Svg.linearGradient [ Svg.Attributes.id ("Gradient-" ++ String.fromInt index), x1 "0", y1 "0", x2 "1", y2 "0", gradientUnits "userSpaceOnUse" ]
+ [ Svg.stop [ Svg.Attributes.offset "0", Svg.Attributes.stopColor "saddlebrown" ] []
+ , Svg.stop [ Svg.Attributes.offset "1", Svg.Attributes.stopColor color ] []
+ ]
+
+
+ line : Int -> String -> Svg msg
+ line index color =
+ let
+ angle =
+ (360 / toFloat (List.length pallete)) * toFloat index
+
+ transformation =
+ "rotate(" ++ String.fromFloat angle ++ "),scale(" ++ String.fromInt radius ++ ",1)"
+
+ url =
+ "url(#Gradient-" ++ String.fromInt index ++ ")"
+ in
+ Svg.line [ x1 "0", y1 "0", x2 "1", y2 "0", transform transformation, stroke url ] []
+
+
+ main =
+ svg [ width "600", height "600", viewBox "-300 -300 600 600" ]
+ [ Svg.g [] (List.indexedMap dot pallete)
+ , Svg.defs [] (List.indexedMap gradient pallete)
+ , Svg.g [] (List.indexedMap line pallete)
+ ]
+ ```
+
+ This may look like a lot, but our `gradient` and `line` functions are very similar to our `dot` function from earlier. In fact we see an essential principle of good programming design here. We spent a lot of time banging our heads over gradients. Now that we've done that work, we can hide the implementation in our gradient and line functions. Now, if we want to draw a new dot, line, and gradient going from the center to the dot, we only need to add a new item to our palette. Our functions do the rest for us. Our functions conceal our complexity. We can forget about the implementation, so long as we know how to operate them. They're like black boxes, we know what goes in and what comes out, but we don't have to know how they work on the inside.
+
+
=
=<!-- slide -->
=