D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
CSmileska
Full window
Github gist
Quantiles Chart
Built with
blockbuilder.org
<!DOCTYPE html> <meta charset="utf-8"> <style> </style> <body> <div id="stackedbars"> <svg id="stacked" width="500" height="120"></svg> </div> <script src="//d3js.org/d3.v4.min.js"></script> <script> var NBR_TICKS = 6; var data = [ { "category": "Residential", "quantile":[900,1100,1300,1700,2550], "topTriangle": [1300], // min, max "topDiamond": [1850], // eff "bottomTriangle": [1390], // min, max "bottomDiamond": [1801] // eff } ]; function drawChart() { var svg = d3.select("#stacked"), margin = {top: 20, right: 180, bottom: 30, left: 80}, width = +svg.attr("width") - margin.left - margin.right, height = +svg.attr("height") - margin.top - margin.bottom; var g = svg .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var y = d3.scaleBand() .rangeRound([height, 0]) .padding(0.5) .align(0.3); var x = d3.scaleLinear() .rangeRound([0, width]); var z = d3.scaleOrdinal().range(["#CBE7FF", "#8FCCFF", "#56b8fe", "#CBE7FF"]); var topMarkerColor = "#FF7C03"; var topMarkerColor = "#EA4424"; var bottomMarkerColor = "#2E8000"; var keys = data.map(d => d.category).reverse(); y.domain(keys); var xData = data .reduce((a,d) => a.concat(d.quantile).concat(d.topDiamond).concat(d.topTriangle).concat(d.bottomDiamond).concat(d.bottomTriangle), []); x.domain([d3.min(xData), d3.max(xData)]).nice(NBR_TICKS); z.domain(d3.range([0,4])); g.selectAll(".serie") .data(data) .enter().append("g") .attr("class", "serie") .selectAll("rect") .data(function(d) { var a = new Array(d.quantile.length-1); for (var i = 1; i < d.quantile.length; ++i) { a[i-1] = { "category": d.category, "x0": d.quantile[i-1], "x1": d.quantile[i] }; } return a; }) .enter().append("rect") .attr("fill", function(d,i) { return z(i) }) .attr("y", function(d) { return y(d.category) }) .attr("x", function(d) { return x(d.x0) }) .attr("width", function(d) { return x(d.x1) - x(d.x0) + 1 }) // +1 to prevent gaps between rects .attr("height", y.bandwidth()); g.selectAll(".topTriangle") .data(data) .enter().append("g") .attr("class", "topTriangle") .selectAll("path") .data(function(d) {return d.topTriangle.map(e => [d.category, e])}) .enter().append("path") .attr('transform',function(d,i) { return 'translate('+(x(d[1]))+','+(y(d[0]) + y.bandwidth()*0)+') rotate(180)' }) .attr('d', d3.symbol().type( function(d) { return d3.symbolTriangle;}).size(y.bandwidth()*2)) .attr('fill', topMarkerColor) .style("fill-opacity", 1) ; g.selectAll(".bottomTriangle") .data(data) .enter().append("g") .attr("class", "bottomTriangle") .selectAll("path") .data(function(d) {return d.bottomTriangle.map(e => [d.category, e])}) .enter().append("path") .attr('transform',function(d,i) { return 'translate('+(x(d[1]))+','+(y(d[0]) + y.bandwidth()*1)+') rotate(0)' }) .attr('d', d3.symbol().type( function(d) { return d3.symbolTriangle;}).size(y.bandwidth()*2)) .attr('fill', bottomMarkerColor) .style("fill-opacity", 1) ; g.selectAll(".topDiamond") .data(data) .enter().append("g") .attr("class", "topDiamond") .selectAll("path") .data(function(d) {return d.topDiamond.map(e => [d.category, e])}) .enter().append("path") .attr('transform',function(d,i) { return 'translate('+(x(d[1]))+','+(y(d[0]) + y.bandwidth()*0)+') rotate(90)' }) .attr("class","topDiamond") .attr('d', d3.symbol().type( function(d) { return d3.symbolDiamond;}).size(y.bandwidth()*3)) .attr('fill', topMarkerColor) .style("fill-opacity", 1) ; g.selectAll(".bottomDiamond") .data(data) .enter().append("g") .attr("class", "bottomDiamond") .selectAll("path") .data(function(d) {return d.bottomDiamond.map(e => [d.category, e])}) .enter().append("path") .attr('transform',function(d,i) { return 'translate('+(x(d[1]))+','+(y(d[0]) + y.bandwidth()*1)+') rotate(90)' }) .attr("class","topDiamond") .attr('d', d3.symbol().type( function(d) { return d3.symbolDiamond;}).size(y.bandwidth()*3)) .attr('fill', bottomMarkerColor) .style("fill-opacity", 1) ; var flag = 0; var xAxis = d3.axisBottom(x) .tickFormat(function(d) { // flag++; // return flag % 2 == 0 ? null : d; return d; }) .ticks(NBR_TICKS) .tickSize(height) ; g.append("g") .attr("class", "axis axis--x") .style('font-size', '12px') .call(customXAxis); function customXAxis(g) { g.call(xAxis); g.select(".domain").remove(); g.selectAll(".tick line") .attr("stroke-width", "1") .style("stroke-opacity", 0.2) .attr("stroke", "#666"); } console.log(xAxis.tickSizeInner()); var yAxis = d3.axisLeft(y); g.append("g") .attr("class", "axis axis--y") .call(customYAxis); function customYAxis(g) { g.call(yAxis); g.select(".domain").remove() .append("text") .attr("x", 2) .attr("y", y(x.ticks(10).pop())) .attr("dy", "0.35em") .attr("text-anchor", "start") .attr("fill", "#000"); g.selectAll(".tick line").attr("stroke-width", "0"); } const ticks = g.selectAll('.tick line'); let numberOfGeneratedTicks = ticks._groups[0].length; if (numberOfGeneratedTicks > 7) { g.remove(); NBR_TICKS = NBR_TICKS - 1; drawChart(); } } drawChart(); </script> </body>
https://d3js.org/d3.v4.min.js