Published unlisted
Edited
Oct 29, 2020
Insert cell
Insert cell
Changed in fork
viewof day = date({ title: "Date Picker", min: "2020-10-19", max: "2020-10-20",
-
value: "2020-10-19",
+
value: defaultDay,
description: "Only two dates to choose from for demo" })
Insert cell
Changed in fork
-
viewof riderchart = {
+
riderchart = {
const svg = d3.create("svg") .attr("viewBox", [0, 0, width, height]); let x = d3.scaleLinear() .range([0 + margin.left, width - margin.right]); let y = d3.scaleBand() .range([0, height - margin.top - margin.bottom]) .padding(0.1); let xAxisSpecs = d3.axisTop(x) .ticks(6) .tickFormat(x => Math.abs(x)) let yAxisSpecs = d3.axisLeft(y) .tickSize(0) let xAxisGrid = d3.axisTop(x) .ticks(6) .tickSize(-(height - margin.top - margin.bottom)) .tickFormat("") let xAxis = g => g .attr("transform", `translate(0,${margin.top})`) .call(xAxisSpecs) .call(g => g.selectAll(".domain").remove()) const xoffset = -40 let yAxis = g => g .attr("transform", `translate(${margin.left},${margin.top})`) .call(yAxisSpecs) .call(g => g.selectAll(".domain").remove()) .call(g => g.selectAll(".tick text") .attr('x', xoffset-10) .attr('class', 'station-name')) let maxRider = d3.max([d3.max(data, d => -d.pickup), d3.max(data, d => d.dropoff)]) x.domain([-maxRider, maxRider]) y.domain(data.map(d => d.station)) let colorScale = d3.scaleOrdinal() .domain(['pickup','dropoff','waited']) .range(d3.schemePaired.slice(0,3)) // add the x-axis gridlines svg.append("g") .attr("class", "grid") .attr("transform", `translate(0,${margin.top})`) .call(xAxisGrid) // add subway line const linewidth = 8 svg.append('g') .attr("transform", `translate(${margin.left},${margin.top})`) .append('line') .attr('class', 'shuttle') .attr('x1', xoffset) .attr('x2', xoffset) .attr('y1', y('Fire Station') + y.bandwidth()/2) .attr('y2', y('Seward 9N') + y.bandwidth()/2) .attr('stroke', '#319244') .attr('stroke-width', linewidth) // create group for each shuttle stop let rects = svg.selectAll('.shuttle-stop') .data(data) .join('g') .attr('class', 'shuttle-stop') .attr("transform", `translate(0,${margin.top})`) // add elements for each shuttle stop rects.append('circle') .attr('class', 'station') .attr("transform", `translate(${margin.left},0)`) .attr('cx', xoffset) .attr('cy', d => y(d.station) + y.bandwidth()/2) .attr('r', linewidth/2 + 1) .attr('stroke-width', 2) rects.append('text') .attr('class', 'headway') .attr("transform", `translate(${margin.left},0)`) .attr('x', xoffset + 45) .attr('y', d => y(d.station) + y.bandwidth()/2) .attr('dy', '0.35em') .text(d => `${Math.floor(d.headway/60)}:${d3.format('>02')(d.headway%60)}`) rects.append('rect') .attr('class', 'pickup pdw') .attr('x', d => x(-d.pickup)) .attr('y', d => y(d.station)) .attr('width', d => x(d.pickup)-x(0)) .attr('height', y.bandwidth()) .attr("data-tippy-content", d => `${d.station}: ${d.pickup} pickups`) .attr('fill', colorScale('pickup')) rects.append('rect') .attr('class', 'dropoff pdw') .attr('x', d => x(0)) .attr('y', d => y(d.station)) .attr('width', d => x(d.dropoff)-x(0)) .attr('height', y.bandwidth()) .attr("data-tippy-content", d => `${d.station}: ${d.dropoff} dropoffs`) .attr('fill', colorScale('dropoff')) rects.append('rect') .attr('class', 'waited pdw') .attr('x', d => x(-d.waited)) .attr('y', d => y(d.station)) .attr('width', d => x(d.waited)-x(0)) .attr('height', y.bandwidth()) .attr("data-tippy-content", d => `${d.station}: ${d.waited} waited`) .attr('fill', colorScale('waited')) // add axes svg.append("g") .attr("class", "x-axis") .attr("transform", `translate(0,${margin.top})`) .call(xAxis); svg.append("g") .attr("class", "y-axis") .call(yAxis); // headers let headers = svg.append('g') .attr('class', 'header') .attr("transform", `translate(0,${margin.top})`) // title headers.append('text') .attr('transform', `translate(${x(0)},${-50})`) .text(`${d3.sum(data, d => d.dropoff)} riders`) .style('font-size', '2.0em') // x-axis headers headers.append('text') .attr('transform', `translate(${x(-maxRider/2)},${-30})`) .text('pickup') headers.append('text') .attr('transform', `translate(${x(maxRider/2)},${-30})`) .text('dropoff') function updateChart(day) {
-
const T = 750 svg.selectAll('rect.pickup').transition().duration(T) .attr('x', d => x(-d.pickup)) .attr('width', d => x(d.pickup)-x(0)) .attr("data-tippy-content", d => `${d.station}: ${d.pickup} pickups`) svg.selectAll('rect.dropoff').transition().duration(T) .attr('width', d => x(d.dropoff)-x(0)) .attr("data-tippy-content", d => `${d.station}: ${d.dropoff} dropoff`) svg.selectAll('rect.waited').transition().duration(T) .attr('x', d => x(-d.waited)) .attr('width', d => x(d.waited)-x(0)) .attr("data-tippy-content", d => `${d.station}: ${d.waited} waited`)
+
rects.data(rawdata.filter(d => +d.date == +new Date(day))) .transition() .duration(750) .call(g => g.select("rect.pickup") .attr('x', d => x(-d.pickup)) .attr('width', d => x(d.pickup)-x(0)) .attr("data-tippy-content", d => `${d.station}: ${d.pickup} pickups`)) .call(g => g.select("rect.dropoff") .attr('width', d => x(d.dropoff)-x(0)) .attr("data-tippy-content", d => `${d.station}: ${d.dropoff} dropoff`)) .call(g => g.select("rect.waited") .attr('x', d => x(-d.waited)) .attr('width', d => x(d.waited)-x(0)) .attr("data-tippy-content", d => `${d.station}: ${d.waited} waited`))
} return Object.assign(svg.node(), {updateChart}); }
Insert cell
Insert cell
width
Insert cell
height = 600
Insert cell
Insert cell
Removed in parent
defaultDay = "2020-10-19"
Insert cell
Insert cell
Changed in fork
-
data = rawdata.filter(d => +d.date == +new Date(day))
+
data = rawdata.filter(d => +d.date == +new Date(defaultDay))
Insert cell
Insert cell
Insert cell
Insert cell
Changed in fork
tooltip = {
-
viewof riderchart;
+
riderchart;
return tippy(".pdw", { followCursor: true }) }
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require("d3@6", "d3-array@^2.2")
Insert cell
tippy = require("tippy.js")
Insert cell
import {table} from "@tmcw/tables@513"
Insert cell
import {date} from "@jashkenas/inputs"
Insert cell