D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
inspired12
Full window
Github gist
Countdown to Singularity (Log and Linear)
<!DOCTYPE html> <html> <meta charset="utf-8"> <!-- Example based on https://bl.ocks.org/mbostock/3887118 --> <!-- Tooltip example from https://www.d3noob.org/2013/01/adding-tooltips-to-d3js-graph.html --> <link href='https://fonts.googleapis.com/css?family=Codystar:300,400|Ubuntu:300,400,500,700|Tulpen+One|Expletus+Sans:400,600,500,700|Roboto:500,900,100,300,700,400|Oswald:400,300,700' rel='stylesheet' type='text/css'> <link rel="stylesheet" href="https://intentive.info/styles/components.css"> <style> body { font: 11px sans-serif; } .viz{ width:90%; margin:0 auto; } .axis path, .axis line { fill: none; stroke: #B5B5B5; shape-rendering: crispEdges; } .axis text { font: 13px "Ubuntu"; } .dot { stroke: #000; } .tooltip { position: absolute; pointer-events: none; background: white; z-index: 99; font-size: small; border-left: 1px solid #D30000; padding: 1em; border-radius: 20px; } .ui { float: left; } .title { float: left; margin-left: 108px; } .ui #selector { height: 3em; width: 120px; margin: 1.5em; } h2.sub.small { clear: both; margin: 0; padding: 0; margin-left: 110px; } span.numberLabel { width: 70px; overflow: inherit; display: block; margin-top:-5px; } .tooltip div { float: left; position: relative; margin-right:1.5em; } .tooltip h5.large.oswald { margin-top: 15px; padding-top: 0; padding-bottom: 0.75em; line-height: 0px; } </style> <body><script type='text/javascript' id="__bs_script__">//<![CDATA[ document.write("<script async src='/browser-sync/browser-sync-client.1.9.2.js'><\/script>".replace(/HOST/g, location.hostname).replace(/PORT/g, location.port)); //]]></script> <div class="viz"> <span class="title huge oswald">Countdown to the Singularity</span> <div class="ui"> <select id="selector" class="form-control"> <option value="Log">Logarithmic</option> <option value="Linear">Linear</option> </select> </div> <h2 class="sub small"> Chart Countdown to Singularity, Events expressed as Time before Present (Years) on the X axis and Time to Next Event (Years) on the Y axis. </h2> </div> <div class="small ref"> <ul> <li> M.T. Rosing, "13C-Depleted carbon microparticles in >3700-Ma sea-floor sedimentary rocks from west greenland," Science 283.5402 (January 29, 1999): 674-6, See also H. Furnes et al., "Early life recorded in archean pillow lavas," Science 304.5670 (April 23, 2004):578-81; </li> <li> M.T. Rosing, "Early Archaean oxygenic photosynthesis - The observational approach," Geophysical Research Abstracts 7.11202 (2005); </li> <li> W. Altermann and J. Kazmierczak, "Archean microfossils: a reappraisal of early life on Earth," Research in Microbiology 154.9 (November 2003): 611-617; and Technical Comments, "Origin and Significance of Archean Quartzose Rocks at Akilia, Greenland," Science 298.5595 (November 1, 2002): 917, https://sciencemag.org/cgi/content/full/298/5595/917a. </li> <li> S.B. Hedges et al., "A molecular timescale of eukaryote evolution and the rise of complex multicellular life," BMC Evolutionary Biology 4:2 (2004), https://www.pubmedcentral.gov/articlerender.fcgi?pubmedid=15005799. </li> <li> J. W. Valentine, D. Jablonski and D. H. Erwin, "Fossils, molecules and embryos: new perspectives on the Cambrian explosion," Development 126.5 (1999): 851-859, https://dev.biologists.org/cgi/reprint/126/5/851.pdf. </li> <li> R. L. Paton, T. R. Smithson and J. A. Clack, "An amniote-like skeleton from the Early Carboniferous of Scotland," Nature 398 (08 April 8, 1999): 508 - 513. </li> <li> Z.X. Luo, A.W. Crompton and A.L. Sun, "A new mammaliaform from the early Jurassic and evolution of mammalian characteristics," Science 292.5521 (May 25, 2001):1535-40. </li> <li> S. Tavare et al., "Using the fossil record to estimate the age of the last common ancestor of extant primates," Nature 416.6882 (April 18, 2002):726-9. </li> <li> C.B. Stewart and T.R. Disotell, "Primate evolution—in and out of Africa," Current Biology 8 (1998):R582–R588. </li> <li> C.J. Cela-Conde and F.J. Ayala, "Genera of the human lineage," PNAS [Proceedings of the National Academy of Sciences of the United States] 100.13(June 24, 2003): 7684-7689, published online June 6, 2003, https://www.pnas.org/cgi/content/full/100/13/7684. </li> <li> M.G. Leakey et al., "New four-million-year-old hominid species from Kanapoi and Allia Bay, Kenya," Nature 376.6541 (August 17, 1995):565-71. </li> <li> B. Wood and M. Collard, "The human genus," Science 284.5411 (April 2, 1999):65-71. See also Human Evolution at the Smithsonian Institution, https://www.mnh.si.edu/anthro/humanorigins/ha/a_tree.html. </li> <li> Y Kimura, "Examining time trends in the Oldowan technology at Beds I and II, Olduvai Gorge," Journal of Human Evolution 43.3 (September 2002):291-321. </li> <li> A.M. MacLarnon and G.P Hewitt, "The evolution of human speech: The role of enhanced breathing control," American Journal of Physical Anthropology 109.3:341-63. </li> <li> Dennis O'Neil, " Evolution of Modern Humans: Early Archaic Homo sapiens," https://anthro.palomar.edu/homo2/mod_homo_1.htm. </li> <li> T.D. White et al., "Pleistocene Homo sapiens from Middle Awash, Ethiopia," Nature 423 (12 June 2003): 742-747. See also The Middle Awash Research Group, "Immediate predecessor of modern humans found in Africa; 160,000 year old Ethiopian fossils are first homo sapiens," June 2003, https://www.berkeley.edu/news/media/releases/2003/06/11_bones-background.shtml. </li> <li> D. Nadel et al., "Stone Age hut in Israel yields world's oldest evidence of bedding," PNAS [Proceedings of the National Academy of Sciences of the United States] 101.17 (April 27, 2004): 6821-6826, published online April 16, 2004, https://intl.pnas.org/cgi/content/full/101/17/6821. </li> <li> O. Soffer, J. N. Adovasio, and D. C. Hyland, "The 'Venus' Figurines: Textiles, Basketry, Gender and Status in the Upper Paleolithic," Current Anthropology 41 (August/October 2000). </li> <li> Dennis O'Neil, " Evolution of Modern Humans: Early Modern Human Culture," https://anthro.palomar.edu/homo2/mod_homo_5.htm. </li> <li> Bar-Yosef, O. 2002, "The Upper Paleolithic revolution," Annual Review of Anthropology 31: 363-393. </li> <li> H. Pringle, "Neolithic Agriculture: The Slow Birth of Agriculture," Science Vol. 282. no. 5393 (November 18, 1998):1446. </li> <li> Cuneiform Digital Library Initiative https://early-cuneiform.humnet.ucla.edu. </li> <li> E. Tunis, Wheels: A Pictorial History (Baltimore, MD: Johns Hopkins University Press, 2002). </li> <li> McGraw-Hill Encyclopedia of Science & Technology, 9th Edition (New York: McGraw-Hill Professional, 2002). </li> <li> Computer History Museum, Timeline, https://www.computerhistory.org/timeline/timeline.php. </li> </ul> </div> <script src="https://d3js.org/d3.v3.min.js"></script> <script> var margin = {top: 20, right: 20, bottom: 30, left: 110}, width = window.innerWidth*0.7 - margin.left - margin.right, height = window.innerHeight*0.7 - margin.top - margin.bottom; var superscript = "⁰¹²³⁴⁵⁶⁷⁸⁹", formatPower = function(d) { return (d + "").split("").map(function(c) { return superscript[c]; }).join(""); }; /* * value accessor - returns the value to encode for a given data object. * scale - maps value to a visual display encoding, such as a pixel position. * map function - maps from data value to display value * axis - sets up axis Time before Present,Time to Next Event,Event, */ // setup x var xValue = function(d) { return d["Time before Present"];}, // data -> value xScale = d3.scale.log().range([width,0]), // value -> display xMap = function(d) { return xScale(xValue(d));}, // data -> display xAxis = d3.svg.axis().scale(xScale).orient("bottom").ticks(10,function(d){ return 10 + formatPower(Math.round(Math.log(d)/Math.LN10)); }); // setup y var yValue = function(d) { return d["Time to Next Event"];}, // data -> value yScale = d3.scale.log().range([height, 0]), // value -> display yMap = function(d) { return yScale(yValue(d));}, // data -> display yAxis = d3.svg.axis().scale(yScale).orient("left").ticks(10,function(d){ return 10 + formatPower(Math.round(Math.log(d)/Math.LN10)); }); // setup fill color var cValue = function(d) { return "ONE";}, color = d3.scale.category10(); // add the graph canvas to the body of the webpage var svg = d3.select(".viz").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 + ")"); // add the tooltip area to the webpage var tooltip = d3.select("body").append("div") .attr("class", "tooltip") .style("opacity", 0); // load data d3.csv("data.csv", function(error, data) { // change string (from CSV) into number format data.forEach(function(d) { d["Event"] = d["Event"]; d["Time before Present"] = +d["Time before Present"]; d["Time to Next Event"] = +d["Time to Next Event"]; // console.log(d); }); var index = ""; d3.select("#selector").property("selectedIndex", index) .on("change", function(d) { index = this.value update(); }) // don't want dots overlapping axis, so add in buffer to data domain xScale.domain([d3.min(data, xValue)-5, d3.max(data, xValue)+5]); yScale.domain([d3.min(data, yValue)-5, d3.max(data, yValue)+5]); // x-axis svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .append("text") .attr("class", "label ubuntu") .attr("x", width) .attr("y", -6) .style("text-anchor", "end") .text("Time before Present"); // y-axis svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label ubuntu") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("Time to Next Event"); // draw dots svg.selectAll(".dot") .data(data) .enter().append("circle") .attr("class", "dot") .attr("r", 5) .attr("cx", xMap) .attr("cy", yMap) .style("stroke-width",0) // .style("fill", function(d) { return color(cValue(d));}) .style("fill", function(d) { return "#D30000";}) .on("mouseover", function(d) { var target = d3.select(this); target.transition() .duration(750) .attr("r", function(){ return 10; }); tooltip.transition().delay(500) .duration(200) .style("opacity", .9); tooltip.html("<h5 class='large oswald'>"+d["Event"]+"</h5>" + "<div><span class='huge tulpen'>" + commaSeparateNumber(yValue(d)) + "</span><span class='numberLabel ubuntu'>Years until next event</span></div><div> <span class='huge tulpen'>" + commaSeparateNumber(xValue(d)) + "</span><span class='numberLabel ubuntu'>Years ago</span></div>") .style("left", (d3.event.pageX + 5) + "px") .style("top", (d3.event.pageY - 40) + "px"); }) .on("mouseout", function(d) { var target = d3.select(this); target.transition() .duration(750) .attr("r", function(){ return 5; }); tooltip.transition() .duration(500) .style("opacity", 0); }); function update(){ switch(index){ case "Linear": xScale = d3.scale.linear().range([width,0]); // value -> display yScale = d3.scale.linear().range([height, 0]); // value -> display xAxis = d3.svg.axis().scale(xScale).orient("bottom"); yAxis = d3.svg.axis().scale(yScale).orient("left"); break; case "Log": xScale = d3.scale.log().range([width,0]); // value -> display yScale = d3.scale.log().range([height, 0]); // value -> display xAxis = d3.svg.axis().scale(xScale).orient("bottom").ticks(10,function(d){ return 10 + formatPower(Math.round(Math.log(d)/Math.LN10)); }); yAxis = d3.svg.axis().scale(yScale).orient("left").ticks(10,function(d){ return 10 + formatPower(Math.round(Math.log(d)/Math.LN10)); }); break; default: xScale = d3.scale.linear().range([width,0]); // value -> display yScale = d3.scale.linear().range([height, 0]); // value -> display break; } ; var dots = svg.selectAll(".dot"); // dots.exit().remove(); // draw dots // update the scales xScale.domain([d3.min(data, xValue)-1, d3.max(data, xValue)+1]); yScale.domain([d3.min(data, yValue)-1, d3.max(data, yValue)+1]); d3.selectAll(".x.axis") .transition().delay(40).ease('quad').duration(500) .call(xAxis); /* xAx.selectAll(".tick text") .text(null) .filter(powerOfTen) .text(10); xAx.selectAll(".tick text") .append("tspan") .attr("dy", "-.7em") .text(function(d) { return Math.round(Math.log(d) / Math.LN10); }); .append("tspan") .attr("dy", "-.7em") .text(function(d) { return Math.round(Math.log(d) / Math.LN10); }); */ d3.selectAll(".y.axis") .transition().delay(40).ease('cubic').duration(500) .call(yAxis); dots.transition() .delay(function (d,i){ return 500 + (i * 30);}).ease('quad').duration(500) .attr("cx", xMap) .attr("cy", yMap) .style("fill", function(d) { return "#D30000" /*color(cValue(d))*/;}) .style("opacity", 0.7) .attr("stroke-width", 0) } }); function commaSeparateNumber(val){ while (/(\d+)(\d{3})/.test(val.toString())){ val = val.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2'); } return val; } function powerOfTen(d) { return d / Math.pow(10, Math.ceil(Math.log(d) / Math.LN10 - 1e-12)) === 1; } </script> </body> </html>
Modified
http://d3js.org/d3.v3.min.js
to a secure url
https://d3js.org/d3.v3.min.js