@ -317,7 +317,7 @@ In summary what this does is loop through each `circle` in the SVG. For each `c
Let's position the circles horizontally, based on the date that their associated run happened. First, create a time scale. This is like a linear scale, but instead of mapping numeric values to visual points, it maps Dates to visual points. Add the following to the bottom of `app.js`:
Let's position the circles horizontally, based on the date that their associated run happened. First, create a time scale. This is like a linear scale, but instead of mapping numeric values to visual points, it maps Dates to visual points. Add the following to the bottom of `app.js`:
```javascript
```javascript
var xScale = d3.scaleTime(); //scaleTime maps date values with numeric visual points
const xScale = d3.scaleTime(); //scaleTime maps date values with numeric visual points
xScale.range([0,WIDTH]);
xScale.range([0,WIDTH]);
xScale.domain([new Date('2017-10-1'), new Date('2017-10-31')]);
xScale.domain([new Date('2017-10-1'), new Date('2017-10-31')]);
@ -336,10 +336,10 @@ You can now remove the two `console.log()` statements.
Note that the `date` properties of the objects in our `runs` array are strings and not Date objects. This is a problem because `xScale`, as with all time scales, expects its data values to be Date objects. Fortunately, D3 provides us an easy way to convert strings to dates and vice versa. We'll use a specially formatted string, based on the documentation (https://github.com/d3/d3-time-format#locale_format), to tell D3 how to parse the `date` String properties of the objects in our `runs` array into actual JavaScript Date objects. Add the following at the end of `app.js`:
Note that the `date` properties of the objects in our `runs` array are strings and not Date objects. This is a problem because `xScale`, as with all time scales, expects its data values to be Date objects. Fortunately, D3 provides us an easy way to convert strings to dates and vice versa. We'll use a specially formatted string, based on the documentation (https://github.com/d3/d3-time-format#locale_format), to tell D3 how to parse the `date` String properties of the objects in our `runs` array into actual JavaScript Date objects. Add the following at the end of `app.js`:
```javascript
```javascript
var parseTime = d3.timeParse("%B%e, %Y at %-I:%M%p"); //this format matches our data in the runs array
const parseTime = d3.timeParse("%B%e, %Y at %-I:%M%p"); //this format matches our data in the runs array
console.log(parseTime('October 3, 2017 at 6:00PM'));
console.log(parseTime('October 3, 2017 at 6:00PM'));
var formatTime = d3.timeFormat("%B%e, %Y at %-I:%M%p"); //this format matches our data in the runs array
const formatTime = d3.timeFormat("%B%e, %Y at %-I:%M%p"); //this format matches our data in the runs array
console.log(formatTime(new Date()));
console.log(formatTime(new Date()));
```
```
@ -349,7 +349,7 @@ Let's use this when calculating `cx` attributes for our circles. Remove the las
```javascript
```javascript
d3.selectAll('circle')
d3.selectAll('circle')
.attr('cx', function(datum, index){
.attr('cx', (datum, index) => {
return xScale(parseTime(datum.date)); //use parseTime to convert the date string property on the datum object to a Date object, which xScale then converts to a visual value
return xScale(parseTime(datum.date)); //use parseTime to convert the date string property on the datum object to a Date object, which xScale then converts to a visual value
});
});
```
```
@ -367,7 +367,7 @@ At the moment, we're setting arbitrary min/max values for the domains of both di
Go to this part of the code:
Go to this part of the code:
```javascript
```javascript
var yScale = d3.scaleLinear(); //create the scale
const yScale = d3.scaleLinear(); //create the scale
yScale.range([HEIGHT, 0]); //set the visual range (e.g. 600 to 0)
yScale.range([HEIGHT, 0]); //set the visual range (e.g. 600 to 0)
yScale.domain([0, 10]); //set the data domain (e.g. 0 to 10)
yScale.domain([0, 10]); //set the data domain (e.g. 0 to 10)
```
```
@ -375,12 +375,12 @@ yScale.domain([0, 10]); //set the data domain (e.g. 0 to 10)
and change it to this:
and change it to this:
```javascript
```javascript
var yScale = d3.scaleLinear(); //create the scale
const yScale = d3.scaleLinear(); //create the scale
yScale.range([HEIGHT, 0]); //set the visual range (e.g. 600 to 0)
yScale.range([HEIGHT, 0]); //set the visual range (e.g. 600 to 0)
var yMin = d3.min(runs, function(datum, index){
const yMin = d3.min(runs, function(datum, index){
return datum.distance; //compare distance properties of each item in the data array
return datum.distance; //compare distance properties of each item in the data array
})
})
var yMax = d3.max(runs, function(datum, index){
const yMax = d3.max(runs, function(datum, index){
return datum.distance; //compare distance properties of each item in the data array
return datum.distance; //compare distance properties of each item in the data array
})
})
yScale.domain([yMin, yMax]); //now that we have the min/max of the data set for distance, we can use those values for the yScale domain
yScale.domain([yMin, yMax]); //now that we have the min/max of the data set for distance, we can use those values for the yScale domain
@ -394,7 +394,7 @@ Chrome should look like this:
Let's examine what we just wrote. The following code finds the minimum distance:
Let's examine what we just wrote. The following code finds the minimum distance:
```javascript
```javascript
var yMin = d3.min(runs, function(datum, index){
const yMin = d3.min(runs, function(datum, index){
return datum.distance; //compare distance properties of each item in the data array
return datum.distance; //compare distance properties of each item in the data array
})
})
```
```
@ -404,12 +404,12 @@ D3 loops through the `runs` array (the first parameter) and calls the callback f
We can combine both the min/max functions into one `extent` function that returns an array that has the exact same structure as `[yMin, yMax]`. Change the code we just wrote:
We can combine both the min/max functions into one `extent` function that returns an array that has the exact same structure as `[yMin, yMax]`. Change the code we just wrote:
```javascript
```javascript
var yScale = d3.scaleLinear(); //create the scale
const yScale = d3.scaleLinear(); //create the scale
yScale.range([HEIGHT, 0]); //set the visual range (e.g. 600 to 0)
yScale.range([HEIGHT, 0]); //set the visual range (e.g. 600 to 0)
var yMin = d3.min(runs, function(datum, index){
const yMin = d3.min(runs, (datum, index) => {
return datum.distance; //compare distance properties of each item in the data array
return datum.distance; //compare distance properties of each item in the data array
})
})
var yMax = d3.max(runs, function(datum, index){
const yMax = d3.max(runs, (datum, index) => {
return datum.distance; //compare distance properties of each item in the data array
return datum.distance; //compare distance properties of each item in the data array
})
})
yScale.domain([yMin, yMax]); //now that we have the min/max of the data set for distance, we can use those values for the yScale domain
yScale.domain([yMin, yMax]); //now that we have the min/max of the data set for distance, we can use those values for the yScale domain
@ -418,9 +418,9 @@ yScale.domain([yMin, yMax]); //now that we have the min/max of the data set for
to this:
to this:
```javascript
```javascript
var yScale = d3.scaleLinear(); //create the scale
const yScale = d3.scaleLinear(); //create the scale
yScale.range([HEIGHT, 0]); //set the visual range (e.g. 600 to 0)
yScale.range([HEIGHT, 0]); //set the visual range (e.g. 600 to 0)
var yDomain = d3.extent(runs, function(datum, index){