Day 1
Let’s Make a Dot!
Today we are going to learn about
Scalable Vector Graphics
Cartesian coordinates systems
Layouts with Elm UI
Lists

The problem

We want to display a dot at the center of the screen, like this:
Below is the complete code to draw a dot like this, but don’t type it in your editor yet! We are going to recreate it together, step by step.
Elm
1
module Main exposing (main)
2
3
import Element
4
import Svg
5
import Svg.Attributes
6
7
8
main =
9
Svg.svg
10
[ Svg.Attributes.viewBox "-300 -300 600 600"
11
]
12
[ Svg.circle
13
[ Svg.Attributes.r "10"
14
, Svg.Attributes.cx "0"
15
, Svg.Attributes.cy "0"
16
, Svg.Attributes.fill "skyblue"
17
]
18
[]
19
]
20
|> Element.html
21
|> Element.layout
22
[ Element.width Element.fill
23
, Element.height Element.fill
24
]
25
26
We are going to use a technology called
SVG (Scalable Vector Graphics)
. It’s all about drawing shapes on the screen. Let’s install an Elm Package to help us work with SVG. Go to
and type
elm/svg
in the search box. After a short while a list of suggested packages should show up. Install the one called simply
svg
.
Now that we have
elm/svg
installed, we can write the code that will draw a dot for us. Change the code to look like this:
Elm
1
module Main exposing (main)
2
3
import Svg
4
import Svg.Attributes
5
6
7
main =
8
Svg.svg []
9
[ Svg.circle
10
[ Svg.Attributes.r "10" ] []
11
]
12
13
14
Click
COMPILE
, you should see something like this:
At this point we have a dot on the screen - it’s at the top left corner of the viewport (the area of the browser window where the content is displayed). We can see only a quarter of it - the rest is outside of the viewport.
It’s a good start, but the dot is not in the center of the screen yet. Let’s try to understand why it is where it is.
First we have to realize that the dot is inside an
svg
element that itself has a position, width and height. We can make the background of the
svg
element pink to see where it is:
Elm
1
module Main exposing (main)
2
3
import Svg
4
import Svg.Attributes
5
6
7
main =
8
Svg.svg [ Svg.Attributes.style "background: pink" ]
9
[ Svg.circle
10
[ Svg.Attributes.r "10" ]
11
[]
12
]
13
14
15
Click
COMPILE
and it should reveal something like this:
Since the dot is inside the
svg
element, and the
svg
element doesn’t cover the center of the screen, it’s impossible to place the dot at the center. Before anything else, let’s make the
svg
fill entire
viewport
.
To do this we will use a package called
mdgriffith/elm-ui
. It makes laying out elements relatively easy. Go to
and install elm-ui.
Now let’s use the package. Change the code to look like this:
Elm
1
module Main exposing (main)
2
3
import Element
4
import Svg
5
import Svg.Attributes
6
7
8
main =
9
Svg.svg
10
[ Svg.Attributes.style "background: pink"
11
, Svg.Attributes.height "100%"
12
, Svg.Attributes.width "100%"
13
]
14
[ Svg.circle
15
[ Svg.Attributes.r "10"
16
]
17
[]
18
]
19
|> Element.html
20
|> Element.layout
21
[ Element.width Element.fill
22
, Element.height Element.fill
23
]
24
25
Don’t worry if it all looks like black magic now. We will discuss what it all means on
Day 3
of the workshop.
For now let’s just note that on line 3 we have added a new
import
statement for
Element
module (similar to how we did it for
Svg
and
Svg.Attributes
before).
After imports our code looks the same at first:
main
is an
svg
element containing the
circle
, but we have added two new attributes
width
an
height
, both set to
"100%"
. We will talk more about attributes later today.
Then there are some new things on lines 19 - 23. First is the pipe operator (
|>
). We use it to pass the
svg
element together with the
circle
inside it into `Element.html` function (we need to convert it into an
Element
) and then to pass this
Element
into an
Element.layout
which will fill the viewport with its contents. Again, more about the pipe and functions on day 3.
Click
to format your code and then click
COMPILE
. The SVG space now fills the entire viewport. Even the small white margin is gone!
It should now be possible to place our dot in the center of the screen. Currently the dot is in the top left corner of the viewport, but at least the parent
svg
element is covering it, so the center of the viewport is somewhere within the
svg
element.

The Coordinates

We will now explore how child elements (like our
circle
) are positioned inside the parent
svg
element.
One method is to use the
cartesian coordinates system
. To get some intuition about it, imagine that you are a villain in an old James Bond movie. For some sinister purpose you need to tell somebody exactly where a flower pot is located on a large table. The problem is that you can only communicate through an old fashioned phone
. To fool mr. Bond you need to be very precise, so saying something like “it’s roughly in the middle” won’t work.
TODO: Image of the table, the flower pot and the villain
However, if you had a ruler, you could say: “it’s 63.3cm from the top edge and 27.1cm from the left edge”. To do that you would need to previously agree which edge is left and which is top - not so obvious in case of a table. Fortunately in SVG we have this sort of agreement made for us. We always measure from the top and left edge of the viewport.
The distance from the left edge is called
x
and the distance from the top is called
y
. The bigger the
x
the more to the right goes the element. The bigger the
y
the more it goes down. Try it out:
xyO{ x = 0, y = 0}
Adjust the sliders below to change the
x
and
y
coordinates of the dot. It’s like moving the flower pot on the table by describing how far left, right, up or down it should be.
Initially the center of the dot is at a point called
the origin
:
{ x = 0, y = 0}
. The origin is in the top left corner of the viewport. That’s why only a quarter of the dot is visible. If we want to help our dot get out of hiding, we’ll have to place the center of the dot at a point with positive
x
and
y
values.
To change the position of the dot, we can use the
cx
and
cy
attributes of the
circle
element, like this:
Elm
1
module Main exposing (main)
2
3
import Element
4
import Svg
5
import Svg.Attributes
6
7
8
main =
9
[ Svg.circle
10
[ Svg.Attributes.r "10"
11
, Svg.Attributes.cx "100"
12
, Svg.Attributes.cy "50"
13
]
14
[]
15
]
16
|> Svg.svg
17
[ Svg.Attributes.height "100%"
18
, Svg.Attributes.width "100%"
19
, Svg.Attributes.style "background: pink"
20
]
21
|> Element.html
22
|> Element.layout
23
[ Element.width Element.fill
24
, Element.height Element.fill
25
]
26
27
28
The
cx
stands for
center x
and
cy
for
center y
, where center refers to the circle. We will discuss what the center of the circle is in more exact terms on day 2, but you probably get the concept.
Now the dot is not in the corner anymore, but it’s not in the center yet. If we want our dot to be exactly in the center of the screen, we’ll have to set
cx
and
cy
to values equal to exactly half of the
width
and
height
of the SVG viewport. We could calculate the position of the circle as:
cx = width / 2 cy = height / 2
There is a problem though! We don’t actually know the width and height of the SVG viewport. All we know is that it will fill all the available space, but this can be different on different devices:
Fortunately, we don’t need to know the width and height of the
svg
element! That’s why it’s called
scalable
. We can work with it without knowing the actual scale on the screen.

The ViewBox

You can imagine an SVG element as an infinite surface on which elements are placed. Which elements you see, depends on where you look. And where you look is called the
viewbox
. It has four properties:
top
,
left
,
width
and
height
.
It works a little bit like a photo camera pointing directly at the surface. You can move it up, down (along the
y
axis) and left and right (along the
x
axis). You can also change its focal length to cover more or less area. Unlike a lens of the camera you set the width and height separately. If you set it so that the dot is in the middle of your frame, then no matter how big the print of the picture will be, the dot will always be in the center. Increasing the
width
and
height
of the viewbox will make more of the surrounding surface visible and the dot will become smaller, but its position won’t change. Let’s see it in action:
xyO
xyO
On the left and the right side we show the same set of elements: a dot at the origin and two axes (
x
going from left to right and
y
going top - down). The pink rectangle represents the viewbox. Normally it is not visible, but we display it here to help you understand how it works.
On the right there is a window with a viewport inside. Everything covered by the viewbox will be displayed in the viewport. Their sizes are independent, so the shapes will be scaled to fit. You can also set the option to preserve the aspect ratio to prevent the shapes from being stretched.
You cannot control the size of the window or the viewport. All you can do is play with the viewbox. Try calibrating the
left
,
top
,
width
and
height
properties of the viewbox so that the dot is in the center of the viewport.
Here is how I would do it. First pick any number for the
width
, say
20
. Then you have to move the left edge half way (
20 / 2 = 10
) to the left. Once you click on a slider you can use
and
keys to precisely set the value. Moving to the left means making the value lesser, and since we start from
0
we will end up at
-10
. Do the same for
height
and
top
. The dot should be exactly in the center of the viewbox and the viewport.
The formula is simple:
left = - (width / 2) top = - (height / 2)
So instead of moving the dot in the SVG plane, we change where we look by moving the viewbox. By setting it that way, we know that the distance from the left and right edge of the screen to the center of the dot will be the same. We don’t know exactly what it will be (because we don’t control the size of the viewport), but it will always be equal. That’s the definition of being in the center!
In the code we set the viewbox as an attribute of the
svg
element, like this:
Elm
1 - 7
unfold
8
main =
9
[ Svg.circle
10
[ Svg.Attributes.r "10"
11
, Svg.Attributes.cx "0"
12
, Svg.Attributes.cy "0"
13
]
14
[]
15
]
16
|> Svg.svg
17
[ Svg.Attributes.height "100%"
18
, Svg.Attributes.width "100%"
19
, Svg.Attributes.style "background: pink"
20
, Svg.Attributes.viewBox "-300 -300 600 600"
21
]
22
|> Element.html
23
|> Element.layout
24
[ Element.width Element.fill
25
, Element.height Element.fill
26
]
27
28
There are only two changes here. First we reset the
cx
and
cy
attributes of the
circle
back to
"0"
(on lines 11 and 12). We want the dot to be back at origin. Then we set up the position of the viewbox on line 20. Try experimenting with different values. If you set them right and refresh the browser the dot should be in the center of the screen.
You can also remove line 19 to remove the pink background, or set it to some other color.

Color

Speaking of colors, now that we’ve centered our dot, it’s time to give it a color! We do it by adding a
fill
attribute to the
circle
element, like this:
Elm
1 - 7
unfold
8
main =
9
[ Svg.circle
10
[ Svg.Attributes.r "10"
11
, Svg.Attributes.cx "0"
12
, Svg.Attributes.cy "0"
13
, Svg.Attributes.fill "skyblue"
14
]
15
[]
16
]
17 - 28
unfold
The only change is on line 13. Reload the browser and see this:
That’s exactly what we were trying to achieve. Scroll up to the problem section to compare.
Please remember to save your code using the
save
button in Ellie. When saved, copy the address and send it to us.
Congratulations!
We really hope you enjoyed this first day of our workshop. See you at
Day 2
!