D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
alansmithy
Full window
Github gist
The Costner Effect
<!DOCTYPE html> <meta charset="utf-8"> <head> <title>The Costner Effect</title> <style> body{font-family:sans-serif;background-color:#dedede} #container { width: 800px; margin-left: auto; margin-right: auto; margin-top: 30px; background-color: white; box-shadow: 2px 2px 4px 5px #ccc; } .yaxis path{fill:none;stroke:none;} .yaxis line{ fill: none; stroke: #333333; stroke-width: 0.1% } .yaxis text{ font-size:12px; } .xaxis path,line{fill:none;stroke:none;} .xaxis text{ font-size:10px; } g.bar { cursor:pointer; } g.bar text { fill:#fff; font-size:10px; text-anchor:middle; opacity:0; } g.bar:hover rect { fill: skyblue; } g.bar:hover text { opacity: 1; } g.lines { pointer-events:none; fill:none; stroke-width:6px; stroke:white; stroke-linecap:round; stroke-linejoin:round; } .titles { font-weight:bold; fill-opacity:0.2; } </style> </head> <body> <div id="container"> </div> <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> <script> var w = 700; var h = 300; var margin={'left':50, 'right':20, 'top':70, 'bottom':50}; var parseDate = d3.time.format("%Y").parse; d3.csv("kevin.csv", function(error, data) { //parse the data data.forEach(function(d) { d.babies=+d.babies; d.gross=+d.gross; }); var dates = data.map(function(d){return d.date}); //extent,scales,axes //var xDomain = d3.extent(data, function(d) {return d.date;}); var max = d3.max([d3.max(data, function(d) {return d.babies;}),d3.max(data, function(d) {return d.gross;})]); var yDomain = [0,max] var xScale = d3.scale.ordinal() .domain(dates) .rangeRoundBands([0,w],0.05) var yScale = d3.scale.linear() .domain(yDomain) .range([h,0]) var xAxis = d3.svg.axis() .scale(xScale) .orient("bottom") var yAxis = d3.svg.axis() .scale(yScale) .orient("left") .ticks(4) //document structure var svg = d3.select("#container").append("svg") .attr("width",function(){ return margin.left+w+margin.right; }) .attr("height",function(){ return margin.top+h+margin.bottom; }) //call y axis svg.append("g").attr("class","yaxis").attr("transform",function(){ return "translate("+margin.left+","+margin.top+")"; }).call(yAxis); svg.append("g").attr("class","xaxis").attr("transform",function(){ return "translate("+margin.left+","+(margin.top+h)+")"; }).call(xAxis); //create groups with bars for baby births var groups = svg.append("g").attr("transform",function(){ return "translate(+"+margin.left+",0)" }).selectAll("g").data(data).enter().append("g") .attr("class","bar").attr("transform",function(d,i){ return "translate("+xScale(d.date)+",0)" }); var rects = groups.append("rect") .attr("height",function(d){ return 0; //return h-yScale(d.babies) }) .attr("width",xScale.rangeBand) .attr("y",function(d){ return h+margin.top //return (h+margin.top)-(h-yScale(d.babies)) }) .attr("fill","steelblue"); groups.append("text") .attr("x",function(d){ return xScale.rangeBand()/2 }) .attr("y",function(d){ return (h+margin.top)-15; }) .text(function(d){ return d.babies; }) .append("tspan") .attr("x",function(d){ return xScale.rangeBand()/2 }) .attr("dy",12) .text("Kevs") //line generator var lineGen = d3.svg.line() .x(function(d) { return xScale.rangeBand()/2+(xScale(d.date)); }) .y(function(d) { return yScale(d.gross); }) //annotations svg.append("text") .attr("id","babyText") .attr("fill-opacity",0) .attr("x",260) .attr("y",215) .attr("fill","steelblue") .text("babies called Kevin") .append("tspan") .attr("x",260) .attr("dy",20) .text("born in Zurich"); //annotations svg.append("text") .attr("id","grossText") .attr("fill-opacity",0) .attr("text-anchor","end") .attr("x",margin.left+w) .attr("y",285) .attr("fill","orange") .text("Costner's box office Gross") .append("tspan") .attr("x",margin.left+w) .attr("dy",20) .text("($m)"); //prepare data for line var lineData=[]; lineData[0] = data.map(function(d){return{ "date":d.date,"gross":d.gross}}); //create group and append line var lineGroup = svg.append("g").attr("class","lines").attr("transform",function(){ return "translate("+margin.left+","+margin.top+")"; }) var line1 = lineGroup.selectAll("path").data(lineData).enter().append("path").attr('d', function(d){ return lineGen(d); }); lineGroup.append("path").attr("d",function(){ return line1.attr("d"); }).attr("stroke","orange").attr("stroke-width","4px") //hide line till animation var lineLen = line1.node().getTotalLength()*2; lineGroup.attr("stroke-dasharray",lineLen + ", "+lineLen).attr("stroke-dashoffset",lineLen); var titles = svg.append("g").attr("class","titles"); titles.append("text") .attr("x",margin.left) .attr("y",30) .attr("font-size",24) .attr("font-weight","normal") .text("The") titles.append("text") .attr("x",margin.left+10) .attr("y",60) .attr("font-size",48) .text("Costner"); titles.append("text") .attr("x",margin.left) .attr("y",85) .attr("font-size",36) .attr("font-weight","normal") .text("Effect"); //source svg.append("text") .attr("x",margin.left) .attr("y",margin.top+h+margin.bottom-5) .attr("font-size",12) .attr("fill","#aaa") .text("Source: canton of Zurich, TheNumbers.com"); //mouseover text var mousetext = svg.append("text") .attr("x",margin.left+w-10) .attr("y",margin.top+20) .attr("text-anchor","end") .attr("fill","#aaa") .text("") var mouseinfo =svg.append("text") .attr("x",margin.left+w-10) .attr("y",margin.top+50) .attr("style","fill:orange;font-size:24px;font-weight:bold") .attr("text-anchor","end") .text("") groups.on("mouseover",function(d){ mousetext.text("Kevin's highlights this year:"); mouseinfo.text(d.highlights) }) groups.on("mouseout",function(d){ mousetext.text("") mouseinfo.text("") }) //transitions rects.transition() .duration(500) .delay(function(d,i){ return i*100; }) .attr("height",function(d){ return h-yScale(d.babies) }) .attr("y",function(d){ return (h+margin.top)-(h-yScale(d.babies)) }) d3.select("#babyText").transition().duration(500).delay(2500).attr("fill-opacity",1) lineGroup.transition() .duration(4000) .delay(3000) .attr("stroke-dashoffset", 0); d3.select("#grossText").transition().duration(500).delay(5500).attr("fill-opacity",1) });//end data load </script> </body> </html>
https://d3js.org/d3.v3.min.js