Skip to content

Instantly share code, notes, and snippets.

@pjsier
Last active July 28, 2017 11:56
Show Gist options
  • Save pjsier/bbb5540138eb9b325cc8399b4488b560 to your computer and use it in GitHub Desktop.
Save pjsier/bbb5540138eb9b325cc8399b4488b560 to your computer and use it in GitHub Desktop.
Square Area Chart
license: mit
<!DOCTYPE html>
<html>
<head>
<title>Square Area Chart</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta charset='utf-8' />
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
#chart {
max-width: 600px;
max-height: 400px;
}
</style>
</head>
<body>
<div id="chart"></div>
<script src="script.js"></script>
<script>
var chart = squareAreaChart();
var data = [
{data: 1024, label: "attempted"},
{data: 558, label: "completed"},
{data: 26, label: "call-ins"}
];
function resize() {
if (d3.select("#chart svg").empty()) {
return;
}
var w = +d3.select("#chart").style("width").replace(/(px)/g, "");
chart.width(w);
chart.height(w*(400/600));
d3.select("#chart").call(chart);
}
document.addEventListener("DOMContentLoaded", function() {
d3.select("#chart").datum(data).call(chart);
d3.select(window).on('resize', resize);
});
</script>
</body>
</html>
function squareAreaChart() {
var margin = {top: 20, right: 20, bottom: 20, left: 20},
width = 600,
height = 400,
dataValue = function(d) { return +d.data; },
labelValue = function(d) { return d.label; },
color = ["#fee0d2", "#fc9272", "#de2d26"];
function chart(selection) {
selection.each(function(data) {
data = data.map(function(d) {
return { value: dataValue(d), label: labelValue(d) };
});
data.sort(function(a, b) { return b.value - a.value; });
// Rect scale should be on squared height (for area, and height is more constrained)
var sqScale = d3.scaleLinear()
.range([0, Math.pow(height-margin.left-margin.right, 2)]);
var sqMax = d3.max(data, function(d) { return d.value; });
sqScale.domain([0, sqMax]);
var svg = d3.select(this).selectAll("svg").data([data]);
var gEnter = svg.enter().append("svg").append("g");
gEnter.append("g").attr("class", "rects")
.selectAll(".data-rects").data(data).enter()
.append("rect").attr("class", "data-rects");
gEnter.selectAll("line.legend")
.data(data).enter()
.append("line").attr("class", "legend");
gEnter.selectAll("text.legend")
.data(data).enter()
.append("text")
.attr("class", "legend")
.attr("font-size", 12);
var svg = selection.select("svg");
svg.attr('width', width).attr('height', height);
var g = svg.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
g.selectAll(".data-rects")
.data(data)
.attr("x", function(d) { return Math.sqrt(sqScale(sqMax)) - Math.sqrt(sqScale(d.value)); })
.attr("y", function(d) { return Math.sqrt(sqScale(sqMax)) - Math.sqrt(sqScale(d.value)); })
.attr("width", function (d) { return Math.sqrt(sqScale(d.value)); })
.attr("height", function (d) { return Math.sqrt(sqScale(d.value)); })
.attr("fill", function (d, i) { return color[i]; });
// Getting midpoint for legend
function legendY(d, i) {
var start = Math.sqrt(sqScale(sqMax)) - Math.sqrt(sqScale(d.value));
if (i === (data.length - 1)) {
var diff = Math.sqrt(sqScale(d.value));
}
else {
var diff = Math.sqrt(sqScale(d.value)) - Math.sqrt(sqScale(data[i+1].value));
}
return start + (diff/2);
}
g.selectAll("line.legend")
.data(data)
.attr("x1", function() { return Math.sqrt(sqScale(sqMax)) + 10; })
.attr("x2", function() { return Math.sqrt(sqScale(sqMax)) + 45; })
.attr("y1", legendY)
.attr("y2", legendY)
.attr("stroke", "#000000")
.attr("stroke-width", 0.5);
g.selectAll("text.legend")
.data(data)
.attr("x", function() { return Math.sqrt(sqScale(sqMax)) + 50; })
.attr("y", function(d, i) { return legendY(d, i) + 5; })
.text(function(d) { return d3.format(",")(d.value) + " " + d.label; });
});
}
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.dataValue = function(_) {
if (!arguments.length) return dataValue;
dataValue = _;
return chart;
};
chart.labelValue = function(_) {
if (!arguments.length) return labelValue;
labelValue = _;
return chart;
};
chart.color = function(_) {
if (!arguments.length) return color;
color = _;
return chart;
};
return chart;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment