D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
emagee
Full window
Github gist
Small multiples (line graphs), with tooltips
<!DOCTYPE html> <meta charset="utf-8"> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script> <title>ISBN counts, 2002-2012</title> <style> body { font: 10px sans-serif; margin: 10px; } /* Max width of the mainSVG div set to 90% to make sure tool tips don't get cut off*/ #mainSVG { max-width: 90%; } .line { fill: none; stroke: #426789; stroke-width: 4px; } .area { fill: #e8eef4; } g#xAxisG text, g#yAxisG text { stroke: none; fill: silver; font-size: 9px; } header, div#source { margin-left: 40px; margin-bottom: 38px; max-width: 75%; } header p { font-size: 1.4em; line-height: 1.25em; } div#source p { font-size: 11px; } h1 { color: #B35959; margin-bottom: 6px; font-size: 2.5em; } h2 { color: #426789; margin-top: 4px; margin-bottom: 20px; font-weight: bold; font-size: 1.5em; } .small { font-size: .85em; } a:-webkit-any-link { color: -webkit-link; text-decoration: none; cursor: auto; color: #426789; } a:any-link { color: -webkit-link; text-decoration: none; cursor: auto; color: #426789; } a:link, a:visited, a:hover, a:active { color: #426789; text-decoration: none; } /* testing: */ div.tooltip { position: absolute; text-align: center; width: 150px; height: 56px; padding: 4px; font: 12px sans-serif; background: #cfcf93; border: 0px; border-radius: 8px; pointer-events: none; line-height: 18px; } p.instruction { color: #426789; font-style: italic; } </style> <body> <header> <h1>ISBN counts for print adult nonfiction books, 2002–2012</h1> <h2>By the subject reported by Bowker customers when registering a book's ISBN</h2> <p>According to Wikipedia, “...Bowker provides bibliographic information on published works to the book trade, including publishers, booksellers, libraries, and individuals... Bowker is the exclusive U.S. agent for issuing International Standard Book Numbers (ISBNs), a universal method of identifying books in print.” <span class="small">(<a href = "https://en.wikipedia.org/wiki/R.R._Bowker">https://en.wikipedia.org/wiki/R.R._Bowker</a>, accessed July 31, 2015)</span></p> <p>Additional books are classified under “non-traditional” or “unclassified;” these are not included in this chart. These ISBNs ranged in count from 247,777 to 2,042,840 per year during this ten-year period.</p> <p class="instruction">→ Hover over the lines to get specific ISBN counts for each year. </p> </header> <div id="mainSVG"></div> <div id="source"> <p>Source: <a href="https://www.bowker.com/documents/isbn-output-report-2002-2013.html">https://www.bowker.com/documents/isbn-output-report-2002-2013.html</a></p> </div> <script> /* The addCommas function is from https://www.mredkj.com/javascript/nfbasic.html. It's used to format the ISBN counts in the tooltips. */ function addCommas(nStr) { nStr += ''; z = nStr.split('.'); z1 = z[0]; z2 = z.length > 1 ? '.' + x[1] : ''; var rgz = /(\d+)(\d{3})/; while (rgz.test(z1)) { z1 = z1.replace(rgz, '$1' + ',' + '$2'); } return z1 + z2; } var margin = {top: 8, right: 15, bottom: 20, left: 40}, width = 180 - margin.left - margin.right, height = 120 - margin.top - margin.bottom; var parseDate = d3.time.format("%Y").parse; var x = d3.time.scale() .range([10, width+10]); var y = d3.scale.linear() .range([height, 0]); var area = d3.svg.area() .x(function(d) { return x(d.date); }) .y0(height) .y1(function(d) { return y(d.count); }); var line = d3.svg.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.count); }); d3.csv("bowker-data-clean-reformatted-3.csv", type, function(error, data) { // Nest data by subject. var subjects = d3.nest() .key(function(d) { return d.subject; }) .entries(data); // Compute the maximum count per subject, needed for the y-domain. subjects.forEach(function(s) { s.maxCount = d3.max(s.values, function(d) { return d.count+500; }); }); // Compute the minimum and maximum date across subjects. // We assume values are sorted by date. x.domain([ d3.min(subjects, function(s) { return s.values[0].date; }), d3.max(subjects, function(s) { return s.values[s.values.length - 1].date; }) ]); // Add an SVG element for each subject, with the desired dimensions and margin. var svg = d3.select("#mainSVG").selectAll("svg") .data(subjects) .enter().append("svg") .style("margin-bottom", "10px") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") ; // Add the area path elements. Note: the y-domain is set per element. svg.append("path") .attr("class", "area") .attr("d", function(d) { y.domain([0, 33000]); return area(d.values); }); var toolTipDiv = d3.select("#mainSVG").append("div") .attr("class", "tooltip") .style("opacity", 0); // Add the line path elements. Note: the y-domain is set per element. svg.append("path") .attr("class", "line") .attr("d", function(d) { y.domain([0, 33000]); return line(d.values); }) .on("mouseover", function(s) { /* Help with tooltip data from "Mark" via stackOverflow. Thanks, Mark! */ var xDate = x.invert(d3.mouse(this)[0]), bisect = d3.bisector(function(d) { return d.date; }).left, idx = bisect(s.values, xDate); toolTipDiv.transition() .duration(300) .style("opacity", .9); toolTipDiv.html(s.key + "<br/> Year: " + s.values[idx].date.getFullYear() + "<br/> ISBN count: " + addCommas(s.values[idx].count)) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }) .on("mouseout", function(d) { toolTipDiv.transition() .duration(500) .style("opacity", 0);}); // Add a small label for the symbol name. svg.append("text") .attr("x", (width + 12)/2) .attr("y", height - 85) .style("text-anchor", "middle") .style("font-family", "helvetica, 'sans-serif'") .style("font-size", "12px") /*.style("font-weight", "bold")*/ .attr("fill", "#B35959") .text(function(d) { return d.key; }); // attempt to add axes var xScale = x; var yScale = y; var yAxis = d3.svg.axis().scale(yScale).orient("left") .tickFormat(function (d) { if ((d / 1000) >= 1) { d = d / 1000 + "K"; } return d; }); svg.append("g").attr("id", "yAxisG").call(yAxis); var xAxis = d3.svg.axis().scale(xScale).orient("bottom").ticks(3); svg.append("g").attr("id", "xAxisG").call(xAxis); d3.selectAll("path.domain").style("fill", "none").style("stroke", "silver"); d3.selectAll("line").style("stroke", "silver"); d3.selectAll("#xAxisG").attr("transform","translate(0,93)"); }); function type(d) { d.count = +d.count; d.date = parseDate(d.date); return d; } </script>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js