D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
sarubenfeld
Full window
Github gist
baseball's winning percentage // 2015 season
<!DOCTYPE html> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style type="text/css"> body { font-family: futura; font-size: 10px; background: rgb(255,247,243); } h1 { font-family: futura; font-size: 10px; } div { display: inline-block; } .divisionText { font-family: futura; font-size: 12px; } .domain { fill: none; stroke: #000; } .axis line { stroke: #bfbfbf; stroke-dasharray: 2, 2; stroke-linecap: "round"; shape-rendering: crispEdges; } .teamLines { fill: none; stroke: #000; stroke-width: 2; } .teamNames { font-family: futura; font-size: 6px; } .background-rect { /*fill: #bfbfbf;*/ fill: rgb(247,251,255); opacity: .1; } .axis text { font-family: futura; font-size: 0.8em; } #neighborhoodPopover { position: absolute; text-align: center; padding: 2px; font-family: futura; font-size: 12px; background: #fff; border: 0px; border-radius: 8px; pointer-events: none; opacity: 0; } </style> <body> </body> <script> var margin = {top: 20, right: 20, bottom: 20, left: 40}; var width = 400 - margin.left - margin.right, height = 250 - margin.top - margin.bottom; var colorScale = d3.scaleOrdinal(d3.schemeCategory20b); var parseDate = d3.utcParse("%Y-%m-%d"); d3.csv("games.csv", function(error, data) { if (error) return console.warn(error); console.log(data) data.forEach(function(d) { d.pct = +d.pct; d.date_str2 = parseDate(d.date_str2); d.result = (d.result == "W" ? 1 : 0); }); var divisionOrder = ['west', "central", 'east']; var nestedData = d3.nest() .key(function(d) { return d.league; }) .key(function(d) { return d.division; }) .sortKeys(function(a, b) { return divisionOrder.indexOf(a) - divisionOrder.indexOf(b)}) .key(function(d) { return d.team; }) .rollup(function(teamValues) { return { totalWin: d3.sum(teamValues, function(d) { return d.result }), values: teamValues } }) .sortValues(function(a, b) { return a.value.totalWin - b.value.totalWin }) .entries(data); console.log(nestedData) var leagueDivs = d3.select("body").selectAll(".leagueDivs") .data(nestedData) .enter().append("div") .attr("class","leagueDivs") leagueDivs.append("h1") .text(function(d) { return d.key; }); var divisionGroups = leagueDivs.selectAll("svg") .data(function(d) { return d.values }) .enter().append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") divisionGroups.append("rect") .attr("class", "background-rect") .attr("width", width) .attr("height", height) String.prototype.capitalize = function() { return this.charAt(0).toUpperCase() + this.slice(1); } divisionGroups.append("text") .attr("class","divisionText") .attr("dy", -5) .text(function(d) { return d.key.capitalize(); }) timeScale = d3.scaleUtc() .domain(d3.extent(data, function(d) { return d.date_str2; })) .range([0, width]); var percentScale = d3.scaleLinear() .domain([0,1]) .range([height, 0]); var xAxis = d3.axisBottom(timeScale) .tickSize(-height) .ticks(20) var yAxis = d3.axisLeft(percentScale) .tickFormat(d3.format(".0%")) .tickSize(-width) divisionGroups.append("g") .attr("class", "x axis") .attr("transform","translate(0," + height + ")") .call(xAxis) .selectAll(".tick") .filter(function(d, i) { return i % 5 != 0 }) .select("text") .remove(); divisionGroups .append("g") .attr("class", "y axis") .call(yAxis) var teamLineGenerator = d3.line() .curve(d3.curveBasis) .x(function(d) { return timeScale(d.date_str2); }) .y(function(d) { return percentScale(d.pct); }) var teamOpacityScale = d3.scaleLinear() .domain([40, 90]) .range([0, 1]); divisionGroups.selectAll(".teamLines") .data(function(d) { return d.values }) .enter().append("path") .attr("class","teamLines") .style("stroke-opacity", function(d) { return teamOpacityScale(d.value.totalWin); }) .style("stroke-dasharray", function(d,i) { var dashArrayValue = i*2; return dashArrayValue }) .attr("d", function(d) { return teamLineGenerator(d.value.values); }) .on("mouseenter", function(d) { console.log(d); d3.select(this) .style("stroke-width", 1.5) .style("stroke-dasharray", 0) d3.select("#neighborhoodPopover") .transition() .style("opacity", 1) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY) + "px") // .text(rateById.get(d.id)) .text(function(d) { return d.key; }) }) .on("mouseleave", function(d) { d3.select(this) .style("stroke-width", .25) .style("stroke-dasharray", 1) d3.select("#neighborhoodPopovercountyText") .transition() .style("opacity", 0); }); divisionGroups.selectAll(".teamNames") .data(function(d) { return d.values }) .enter().append("text") .attr("class","teamNames") .text(function(d) { return d.key; }) .attr("x", width) .attr("y", function(d) { var lastValue = d.value.values[d.value.values.length - 1] return percentScale(lastValue.pct); }) d3.selectAll(".east") .select(".y") .selectAll("text") .remove() d3.selectAll(".central") .select(".y") .selectAll("text") .remove() }); </script>
https://d3js.org/d3.v4.min.js