D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
carlkra
Full window
Github gist
Bar Chart and Table
Built with
blockbuilder.org
<!DOCTYPE html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css"> <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } svg { width:100%; height: 100% } .table th{ text-align:center; } .table td{ text-align:center; } .table td:first-child{ text-align:left } .bar {fill: steelblue;} .bar:hover {fill: red} </style> </head> <body> <div class="col-md-12"> <h3 id="market-name">market</h3> </div> <div class="col-md-4"> <div id="page-title"> </div> <div id="roster"></div> </div> <div class="col-md-8"> <div id="area1"> </div> </div> <script> var dateparser = d3.time.format("%m/%d/%Y"); var pctformat = d3.format("%"); var r2precision = d3.format(".2f") var mformat = d3.format(","); var months = {0:"Jan", 1:"Feb", 2:"Mar", 3:"Apr", 4:"May", 5:"Jun", 6:"Jul", 7:"Aug", 8:"Sep", 9:"Oct", 10:"Nov", 11:"Dec" }; var data = []; var columns = ["Period", "Visits", "Bounce Rate", "Avg. Visit Duration" ]; var markets =[]; var marketSelector = d3.select("#page-title") .append("select") .attr("id", "market-selector") .on("change", function() { selectMarket(this.value); }); var margin = {top: 40, right: 50, bottom: 50, left:75 }, width = 700 - margin.left - margin.right, height = 300 - margin.top - margin.bottom; var svg = d3.select("#area1").append("svg") .attr("width",width+ margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("class","viewport") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var y = d3.scale.linear() .range([height,0]); var table = d3.select("#roster") .append("table") .classed("table", true); var thead = table.append("thead"); var tbody = table.append("tbody"); var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1); //start reload //console.log("start reload") var reload = function () { d3.csv("data.csv", function(records){ data = records; data.forEach(function (d) { d.Date = dateparser.parse(d.Date); d.Month = d.Date.getMonth(); d.Year = d.Date.getFullYear(); d.Period = d.Year + "-" + (d.Month+1) d.Visits = +d.Visits; d.Bounces = +d.Bounces; d.Pageviews = +d.Pageviews; d.SPV = +d.SPV; d.TotalSeconds = +d.TotalSeconds; if (markets.indexOf(d.Market)<0) { markets.push(d.Market); }; }); //console.log(data); //establish x and y axes x.domain(data.map(function(d) { return d.Period; })); y.domain([0, d3.max(data, function(d) { return d.Visits; })]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("Left") .ticks(5) .tickFormat(d3.format("s")); svg.append("g") .attr("class", "x-axis") .style("font-size","11px") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y-axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".30em") .style("text-anchor", "end") .style("font-size","12px") .text("visits"); markets.sort(); selectMarket(markets[0]); }); }; //start of redraw function var redraw = function(roster) { var nested_data = []; current_sel = svg.selectAll(".bar").data(nested_data),function(d){return d;}; current_sel.enter().append("rect") .attr("class", "bar") .attr("x", function(d) { return x(d.chartPeriod); }) .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.chartVisits); }) .attr("height", function(d) { return height - y(d.chartVisits);}); current_sel.exit().remove(); var nested_data = d3.nest() .key(function(d) {return d.Period; }).sortKeys(d3.ascending) .rollup(function(v) {return{ visits:d3.sum(v, function(d) {return d.Visits; }), BounceRate : d3.sum(v, function(d) {return d.Bounces; })/d3.sum(v, function(d) {return d.Visits; }), AVD:d3.sum(v, function (d) {return d.TotalSeconds;}) / (d3.sum(v, function(d) {return d.Visits; })-d3.sum(v, function(d) {return d.Bounces; }))/60 };}) .entries(roster); nested_data.forEach(function (d) { d.Period = months[d.key.split("-").pop() - 1] + "-" + d.key.slice(0,4) ; d.Visits = mformat(d.values.visits); d["Bounce Rate"] = pctformat(d.values.BounceRate); d["Avg. Visit Duration"] = r2precision(d.values.AVD) d.chartVisits = +d.values.visits d.chartPeriod = d.Period }); console.log(nested_data); //update axes domains and establish rescaled axes x.domain(nested_data.map(function(d) { return d.chartPeriod; })); y.domain([0, d3.max(nested_data, function(d) { return d.chartVisits; })]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(5) .tickFormat(d3.format("s")); d3.select(".x-axis") .transition() .call(xAxis); d3.select(".y-axis") .transition() .call(yAxis); //update drop-down selector marketSelector.selectAll("option") .data(markets) .enter() .append("option") .attr("value", function(d) { return d; }) .text(function(d) { return d; }) .sort(function(a,b) { return d3.ascending(a,b); }); //update table header and rows thead.selectAll("tr") .data([columns]) .enter() .append("tr") .selectAll("th") .data(function(d) { return d; }) .enter() .append("th") .on("click", function(d) { tbody.selectAll("tr") .sort(function(a,b) { return (d === 'No') ? d3.ascending(+a[d], +b[d]) : d3.ascending(a[d], b[d]) }) .style("background-color", function(d,i) { return (i%2)? "white":"lightgray"; }); }).text(function(d) { return d; }) ; var rows = tbody.selectAll("tr") .data(nested_data); rows.enter() .append("tr") .style("background-color", function(d,i) { return (i%2)? "white":"lightgray"; }); rows.exit().remove(); var cells = rows.selectAll("td") .data(function(row) { return columns.map(function(col) { return row[col]; });}); cells.enter().append("td"); cells.text(function(d) { return d; }); cells.exit().remove(); //redraw chart current_sel = svg.selectAll(".bar").data(nested_data),function(d){return d;}; current_sel.enter().append("rect") .attr("class", "bar") .attr("x", function(d) { return x(d.chartPeriod); }) .attr("width", x.rangeBand()) .attr("y",y(0)) .attr("height",0) .transition() .delay(function (d, i) { return i*50; }) .duration(800) .attr("y", function(d) { return y(d.chartVisits); }) .attr("height", function(d) { return height - y(d.chartVisits);}); current_sel.exit().remove(); //tooltip var div = d3.select("#area1").append("div") .style("position", "absolute") .style("text-align","center") .style("width","120px") .style("height", "3.0 em") .style("font", "1em Open Sans") .style("color", "black") .style("background","white") .style("border-radius", "4px") .style("border", "solid 2px red") .style("opacity", 0); function mouseover(d) { div.html ("Period: " + d.chartPeriod + "<br />" + "Visits: " + d.chartVisits) .style("left", (x(d.chartPeriod)) + 90 + "px") .style ("top", (y(d.chartVisits)) - 10 + "px") .style("opacity",1); } function mouseout() { div.style("opacity", 1e-6) .style("left","1px") .style("top", height+100); } d3.selectAll(".bar") .on("mouseover", mouseover) .on("mouseout", mouseout); }; //end of redraw function var selectMarket = function(marketId) { var roster = data.filter(function(d) { return d.Market === marketId; }); redraw(roster); d3.select("#market-name").text(marketId + ": Summary Metrics"); document.getElementById("market-selector").value = marketId; }; reload(); </script> </body> </html>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js