# Adding gridlines

We're going to skip step 5 and use step 6 to get our feet wet with angular math. We'll draw angular grid lines for each month, circular grid lines for temperature, and label both axes.

# Adding gridlines#

To get our feet wet with this angular math, we'll draw our peripherals *before* we draw our data elements.

Let's switch those steps in our code.

` // 6. Draw peripherals`

` // 5. Draw data`

If your first thought was "but the checklist!", here's a reminder that our chart drawing checklist is here as a friendly guide, and we can switch the order of steps if we need to.

Drawing the grid lines (peripheral) first is helpful in cases like this where we want our data elements to layer *on top*. If we wanted to keep our steps in order, we could also create a `<g>`

element *first* to add our grid lines to *after*.

Creating a group to hold our grid elements is also a good idea to keep our elements organized -- let's do that now.

const peripherals = bounds.append("g")

### Draw month grid lines#

Next, let's create one "spoke" for each month in our dataset. First, we'll need to create an array of each month. We already know what our first and last dates are -- they are the `.domain()`

of our `angleScale`

. But how can we create a list of each month between those two dates?

The **d3-time** module has various *intervals*, which represent various units of time. For example, `d3.timeMinute()`

represents every minute and `d3.timeWeek()`

represents every week.

Each of these intervals has a few methods -- we can see those methods in the documentation, and also if we double-click into the source code in our dev tools console.

For example, we could use the `.floor()`

method to get the first "time" in the current month:

d3.timeMonth.floor(new Date())

d3 time intervals also have a `.range()`

method that will return a list of datetime objects, spaced by the specified interval, between two dates, passed as parameters.

Let's try it out by creating our list of months!

const months = d3.timeMonth.range(angleScale.domain())

console.log(months)

Great! Now we have an array of datetime objects corresponding to the beginning of each month in our dataset.

**d3-time** gives us shortcut aliases that can make our code even more concise -- we can use `d3.timeMonth()`

instead of `d3.timeMonth.range()`

.

const months = d3.timeMonths(angleScale.domain())

Let's use our array of months and draw one `<line>`

per month.

const gridLines = months.forEach(month => {

return peripherals.append("line")

})

We'll need to find the angle for each month -- let's use our `angleScale`

to convert the date into an angle.

const gridLines = months.forEach(month => {

const angle = angleScale(month)

return peripherals.append("line")

})

Each *spoke* will start in the middle of our chart -- we could start those lines at `[dimensions.boundedRadius, dimensions.boundedRadius]`

, but most of our element will need to be shifted in respect to the center of our chart.

Remember how we use our **bounds** to shift our chart according to our `top`

and `left`

margins?

To make our math simpler, let's instead shift our **bounds** to *start* in the center of our chart.

This will help us when we decide where to place our data and peripheral elements -- we'll only need to know where they lie *in respect to the center of our circle*.

const bounds = wrapper.append("g")

.style("transform", `translate(${

dimensions.margin.left + dimensions.boundedRadius

` }px, ${`

dimensions.margin.top + dimensions.boundedRadius

` }px)`)`

We'll need to convert from *angle* to `[x, y]`

coordinate many times in this chart. Let's create a function that makes that conversion for us. Our function will take two parameters:

the

**angle**the

**offset**

and return the `[x,y]`

coordinates of a point rotated `angle`

radians around the center, and `offset`

time our circle's radius (`dimensions.boundedRadius`

). This will give us the ability to draw elements at different **radii** (for example, to draw our precipitation bubbles slightly outside of our temperature chart, we'll offset them by `1.14`

times our normal radius length).

const getCoordinatesForAngle = (angle, offset=1) => []

To convert an angle into a coordinate, we'll dig into our knowledge of trigonometry. Let's look at the right-angle triangle (a triangle with a 90-degree angle) created by connecting our *origin point* (`[0,0]`

) and our *destination point* (`[x,y]`

).

The numbers we already know are **theta (θ)** and the **hypotenuse** (`dimensions.boundedRadius * offset`

). We can use these numbers to calculate the lengths of the `adjacent`

and `opposite`

sides of our triangle, which will correspond to the `x`

and `y`

position of our *destination point*.

Because our triangle has a *right angle*, we can multiply the `sine`

and `cosine`

of our `angle`

by the length of our **hypotenuse** to calculate our `x`

and `y`

values (remember the **soh cah toa** mnenomic?).

This page is a preview of *Fullstack D3 Masterclass*