You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
3.3 KiB

var WIDTH = 800;
var HEIGHT = 600;
var runs = [
{
id: 1,
date: 'October 1, 2017 at 4:00PM',
distance: 5.2
},
{
id: 2,
date: 'October 2, 2017 at 5:00PM',
distance: 7.0725
},
{
id: 3,
date: 'October 3, 2017 at 6:00PM',
distance: 8.7
}
];
d3.select('svg')
.style('width', WIDTH)
.style('height', HEIGHT);
var parseTime = d3.timeParse("%B%e, %Y at %-I:%M%p");
var formatTime = d3.timeFormat("%B%e, %Y at %-I:%M%p");
var xScale = d3.scaleTime();
xScale.range([0,WIDTH]);
var xDomain = d3.extent(runs, function(datum, index){
return parseTime(datum.date);
});
xScale.domain(xDomain);
var yScale = d3.scaleLinear(); //create the scale
yScale.range([HEIGHT, 0]); //set the visual range (e.g. 600 to 0)
var yDomain = d3.extent(runs, function(datum, index){
return datum.distance; //compare distance properties of each item in the data array
})
yScale.domain(yDomain);
var render = function(){
d3.select('svg').selectAll('circle') //since no circles exist, we need to select('svg') so that d3 knows where to append the new circles
.data(runs) //attach the data as before
.enter() //find the data objects that have not yet been attached to visual elements
.append('circle'); //for each data object that hasn't been attached, append a <circle> to the <svg>
d3.selectAll('circle')
.attr('cy', function(datum, index){
return yScale(datum.distance);
});
d3.selectAll('circle')
.attr('cx', function(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
});
}
render();
var bottomAxis = d3.axisBottom(xScale); //pass the appropriate scale in as a parameter
d3.select('svg')
.append('g') //put everything inside a group
.call(bottomAxis) //generate the axis within the group
.attr('transform', 'translate(0,'+HEIGHT+')');
var leftAxis = d3.axisLeft(yScale);
d3.select('svg')
.append('g')
.call(leftAxis); //no need to transform, since it's placed correctly initially
var createTable = function(){
d3.select('tbody').html(''); //clear out all rows from the table
for (var i = 0; i < runs.length; i++) {
var row = d3.select('tbody').append('tr');
row.append('td').html(runs[i].id);
row.append('td').html(runs[i].date);
row.append('td').html(runs[i].distance);
}
}
createTable();
d3.select('svg').on('click', function(){
var x = d3.event.offsetX; //gets the x position of the mouse relative to the svg element
var y = d3.event.offsetY; //gets the y position of the mouse relative to the svg element
var date = xScale.invert(x) //get a date value from the visual point that we clicked on
var distance = yScale.invert(y); //get a numeric distance value from the visual point that we clicked on
var newRun = { //create a new "run" object
id: runs[runs.length-1].id+1, //generate a new id by adding 1 to the last run's id
date: formatTime(date), //format the date object created above to a string
distance: distance //add the distance
}
runs.push(newRun); //push the new run onto the runs array
createTable(); //render the table
render(); //add this line
});