D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
TommyCoin80
Full window
Github gist
Bin Zooming Histogram
<!DOCTYPE html> <meta charset="utf-8"> <head> <link href='https://fonts.googleapis.com/css?family=Play' rel='stylesheet' type='text/css'> <style> body { margin:auto; font-family: 'Play', sans-serif; font-size:100%; cursor: default; } #dashboard { width:100%; } text { font-family: 'Play', sans-serif; pointer-events: none; } rect { fill:#428bca; } .zoomButton{ font-size:80px; fill:white; } .zoomButton.plus rect{ fill:#5cb85c; } .zoomButton.minus rect{ fill:#d9534f; } .active { opacity:1; transition: opacity 1000ms; } .inactive { opacity:.1; transition: opacity 1000ms; } </style> <script src="https://d3js.org/d3.v4.min.js"></script> <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> <body> <div id="dashboard"></div> <script> var margin = {top:50,left:50,bottom:50,right:75}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var svg = d3.select("body").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 + ")"); var data = d3.range(1000).map(d3.randomNormal(80,10)); data.sort(function(a,b) { return a-b;}); var x = d3.scaleLinear() .domain(d3.extent(data)) .range([0,width]); var ticks = { req: { min:5, max:40}, got:[]}; (function() { var t = 0; d3.range(ticks.req.min,ticks.req.max+1,1).forEach(function(d) { if( x.ticks(d).length > t) { t = x.ticks(d).length; ticks.got.push(x.ticks(d).length) } }); })(); ticks.def = ticks.got[Math.round(ticks.got.length/2)-1]; ticks.cur = ticks.def; var bins = binData(data,x,ticks.def); var y = d3.scaleLinear() .range([height,0]) .domain([0,d3.max(bins.map(function(d) { return d.count}))]); var xAxis = d3.axisBottom(x), yAxis = d3.axisLeft(y); svg.selectAll(".bar") .data(bins) .enter() .append("rect") .attr("class","bar") .attr("width", x(bins[0].max) - x(bins[0].min) - 2) .attr("height", function(d) { return height - y(d.count) }) .attr("x", function(d) { return x(d.min)}) .attr("y", function(d) { return y(d.count)}); svg.append("g") .attr("class","axis x") .attr("transform","translate(0," + height + ")") .call(xAxis) svg.append("g") .attr("class","axis y") .call(yAxis); var plusButton = svg.append("g") .attr("class","zoomButton plus") .attr("transform","translate(" + width + ",0)") .classed("active", ticks.got.indexOf(ticks.cur)<(ticks.got.length-1)) .classed("inactive", ticks.got.indexOf(ticks.cur)==(ticks.got.length-1)) .on("click",zoom) plusButton.append("rect") .attr("width",50) .attr("height",50) plusButton.append("text") .attr("x",25) .attr("y", 50) .text("+") .attr("text-anchor","middle") var minusButton = svg.append("g") .attr("class","zoomButton minus") .attr("transform","translate(" + width + "," + 55+ ")") .classed("active", ticks.got.indexOf(ticks.cur)>0) .classed("inactive", ticks.got.indexOf(ticks.cur)==0) .on("click", zoom) minusButton.append("rect") .attr("width",50) .attr("height",50) minusButton.append("text") .attr("x",25) .attr("y", 50) .attr("dy",-2) .text("-") .attr("text-anchor","middle"); var duration = 1000; function binData(dat, s, t) { var b = []; s.ticks(t).forEach(function(d,i) { if(i < x.ticks(t).length -1) { b.push({bin:i,min:d,max:x.ticks(t)[i+1]}) } }); b.forEach(function(d) { d.count = dat.filter(function(e) { return e >= d.min && e < d.max}).length; }) return b; } function zoom() { if(d3.select(this).classed("inactive")) { return 0;} if(d3.select(this).classed("plus")) { ticks.cur = ticks.got[ticks.got.indexOf(ticks.cur) + 1] } else { ticks.cur = ticks.got[ticks.got.indexOf(ticks.cur) - 1] } minusButton.classed("active", ticks.got.indexOf(ticks.cur)>0) .classed("inactive", ticks.got.indexOf(ticks.cur)==0) plusButton.classed("active", ticks.got.indexOf(ticks.cur)<(ticks.got.length-1)) .classed("inactive", ticks.got.indexOf(ticks.cur)==(ticks.got.length-1)) svg.select(".axis.x") .transition() .duration(duration) .call(xAxis.ticks(ticks.cur)) var newBins = binData(data,x,ticks.cur); y.domain([0,d3.max(newBins.map(function(d) { return d.count}))]); svg.select(".axis.y") .transition() .duration(duration) .call(yAxis); svg.selectAll(".bar") .transition() .duration(duration) .attr("height", function(d) { return height - y(0) }) .attr("y", function(d) { return y(0)}) .transition() .remove(); svg.selectAll(null) .data(newBins) .enter() .append("rect") .attr("class","bar") .attr("width", x(newBins[0].max) - x(newBins[0].min) - 2) .attr("height", function(d) { return height - y(0) }) .attr("y", function(d) { return y(0)}) .attr("x", function(d) { return x(d.min)}) .transition() .duration(duration) .attr("height", function(d) { return height - y(d.count) }) .attr("y", function(d) { return y(d.count)}); } </script>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-scale-chromatic.v1.min.js