Published unlisted
Edited
Nov 2, 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 = { const svg = d3.create("svg") .attr("viewBox", [0, 0, width, height]); let x = d3.scaleLinear() .range([0 + margin.left, width - margin.right]);
+
riderchart = { const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
-
let y = d3.scaleBand() .range([0, height - margin.top - margin.bottom]) .padding(0.1);
+
svg.append(() => style);
-
let xAxisSpecs = d3.axisTop(x) .ticks(6) .tickFormat(x => Math.abs(x))
+
let x = d3.scaleLinear().range([0 + margin.left, width - margin.right]);
-
let yAxisSpecs = d3.axisLeft(y) .tickSize(0)
+
let y = d3 .scaleBand() .range([0, height - margin.top - margin.bottom]) .padding(0.1);
-
let xAxisGrid = d3.axisTop(x) .ticks(6) .tickSize(-(height - margin.top - margin.bottom)) .tickFormat("")
+
let xAxisSpecs = d3 .axisTop(x) .ticks(6) .tickFormat(x => Math.abs(x));
-
let xAxis = g => g .attr("transform", `translate(0,${margin.top})`) .call(xAxisSpecs) .call(g => g.selectAll(".domain").remove())
+
let yAxisSpecs = d3.axisLeft(y).tickSize(0);
-
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 xAxisGrid = d3 .axisTop(x) .ticks(6) .tickSize(-(height - margin.top - margin.bottom)) .tickFormat("");
-
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 xAxis = g => g .attr("transform", `translate(0,${margin.top})`) .call(xAxisSpecs) .call(g => g.selectAll(".domain").remove());
-
let colorScale = d3.scaleOrdinal() .domain(['pickup','dropoff','waited']) .range(d3.schemePaired.slice(0,3))
+
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') );
-
// add the x-axis gridlines svg.append("g") .attr("class", "grid") .attr("transform", `translate(0,${margin.top})`) .call(xAxisGrid)
+
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));
-
// 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})`)
+
let colorScale = d3 .scaleOrdinal() .domain(['pickup', 'dropoff', 'waited']) .range(d3.schemePaired.slice(0, 3));
-
// 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)
+
// add the x-axis gridlines svg .append("g") .attr("class", "grid") .attr("transform", `translate(0,${margin.top})`) .call(xAxisGrid);
-
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)}`)
+
// 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);
-
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'))
+
// 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})`);
-
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'))
+
// 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('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);
+
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)}` );
-
svg.append("g") .attr("class", "y-axis") .call(yAxis);
+
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'));
-
// 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 .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'));
-
return Object.assign(svg.node(), {updateChart});
+
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) { 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
Changed in fork
-
html`<style>
+
style = html`<style>
.header { text-anchor: middle; font-size: 1.0em; } .station { stroke: black; fill: white; } .headway { font-size: 1.0em; text-anchor: end; } .grid line, .x-axis line { stroke: black; stroke-opacity: 0.1; shape-rendering: crispEdges; } .grid path { stroke-width: 0; } .tick text { font-size: 1.5em; } </style>`
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