|
|
|
<!DOCTYPE html> |
|
<html> |
|
<meta charset="utf-8"> |
|
|
|
<!-- Example based on http://bl.ocks.org/mbostock/3887118 --> |
|
<!-- Tooltip example from http://www.d3noob.org/2013/01/adding-tooltips-to-d3js-graph.html --> |
|
<link href='http://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="http://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, http://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), http://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, http://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, http://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, http://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," http://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, http://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, http://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," http://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 http://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, http://www.computerhistory.org/timeline/timeline.php. |
|
</li> |
|
</ul> |
|
|
|
</div> |
|
|
|
<script src="http://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> |