How many stations are there? Data is shared for the trip duration between many stations. Filtering the stations interactively and viewing the data transform can provide additional information that is hidden in the clutter. We will be using the drop down for all the available stations. There is whooping 601 stations in data. There are many stations in which the bike trips are very less.
How to build a drop down with all the stations? D3 can easily rescue us from such activities. All we need is location where we want the drop down, the list that is going to enter into the list. The start and the end stations both are same, so only one drop down is created. Format for creating the drop down is referred from the freeCode camp siteDrop Down reference. We will first create two divs that will float on either side of the scatter plot.
Representing the distance and duration makes the data very physical in nature, because of the involvement of time and distance dimensions. Lets dive into the Pseudo code of bringing the scatter plot on to the svg. There were couple of gotchas during the making of the charts.
Simple Array of elements contains the station names. To place them inside the dropdown framework, understanding of the mechanism how it drop down, selection and events linked with the dropdown works is required. Below code shows the process in action.
Drop down with D3
function buildDropDown(divId, listData, forId, attrName, labelName,rawData) { //Build the start station dropdown const dropStrt = d3.select(`#${divId}`) .append('label') .attr('for',forId) .text(labelName) const startStnDd = dropStrt.append('select') .attr('name',attrName) .attr('class','w-50') .attr('id',forId) //placing the event listener here leads to entire list selected .on('change',function(e, d){ var start = this.value; scatterPlot(rawData,start); }) startStnDd.selectAll('option') .data(listData) .join('option') .attr('value', d => d) .text(d =>d) }
function scatterPlot(tabData, startStation) { filteredData = tabData.filter((d) => d.startStn === startStation); //Domain is attached seperately and called. xScale.domain(d3.extent(filteredData, (d) => d.tripDuration)) yScale.domain(d3.extent(filteredData, (d) => d.haversignDist)) xAxis.transition().duration(1000).call(d3.axisBottom(xScale)); yAxis.transition().duration(1000).call(d3.axisLeft(yScale)); var toolTip = d3 .select("#chart") .append("div") .style("opacity", 0) .attr("class", "ba ph4 pv2 mb2 dib br3 bw2 f6 bg-light-blue"); var mouseOver = function (d) { console.log(d3.mouse(this)); toolTip .html( `Trip Duration: ${d.tripDuration}
Haversign Distance: ${d.haversignDist}
Ride Type:${d.rideableType}` ) .transition() .duration(1000) .style("opacity", 1); }; var mouseOut = function (d) { toolTip.transition().duration(1000).style("opacity", 0); d3.select(this).style("opacity", 0.7); }; const marks = svg .selectAll("circle") .data(filteredData) .join( enter => enter.append('circle') .attr("cx", (d) => xScale(d.tripDuration)) .attr("cy", (d) => yScale(d.haversignDist)) .attr("fill", (d) => ride(d.rideableType)) .attr("r", 5) .style("opacity", 0.7) .on("mouseover", mouseOver) .on("mouseleave", mouseOut), update => update .attr('opacity',0.3) .transition().duration(2500) .attr('opacity',0.9), exit => exit .transition().duration(2500) .attr('transform',(d,i)=> `translate(${d.tripDuration + 25} ${d.haversignDist + 50})`) .remove() )