Skip to content

Instantly share code, notes, and snippets.

@Zhenmao
Created January 3, 2018 06:01
Show Gist options
  • Save Zhenmao/554e595e9f4b200ed17724d71039216e to your computer and use it in GitHub Desktop.
Save Zhenmao/554e595e9f4b200ed17724d71039216e to your computer and use it in GitHub Desktop.
Bar, pie and line charts
<!DOCTYPE html>
<html>
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<button id="bar-button">Bar</button>
<button id="pie-button">Pie</button>
<button id="line-button">Line</button>
<div id="chart"><svg></svg></div>
<script>
var data = [
{unit: "Survey Monkey", value: 25},
{unit: "Qualtrics", value: 12},
{unit: "TypeForm", value: 18}
];
function chart(data, type, withTransition) {
var containerWidth = Math.min(window.innerWidth, 800),
containerHeight = Math.min(window.innerHeight, 400);
d3.select("#chart").select("svg").remove();
var svg = d3.select("#chart")
.attr("data-type", type)
.append("svg");
switch (type) {
case "bar":
bar(data, svg, containerWidth, containerHeight, withTransition); break;
case "pie":
pie(data, svg, containerWidth, containerHeight, withTransition); break;
case "line":
line(data, svg, containerWidth, containerHeight, withTransition);
}
}
function line(data, svg, containerWidth, containerHeight, withTransition) {
var margin = {top: 30, bottom: 50, left: 50, right: 30};
var width = containerWidth - margin.left - margin.right;
var height = containerHeight - margin.top - margin.bottom;
var chartArea = 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 x = d3.scaleBand().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var xAxis = d3.axisBottom().scale(x);
var yAxis = d3.axisLeft().scale(y);
x.domain(data.map(function(d) { return d.unit; }));
y.domain([0, d3.max(data, function(d) { return d.value; })]);
var line = d3.line()
.x(function(d) { return x(d.unit) + x.bandwidth() / 2; })
.y(function(d) { return y(d.value); });
var xaxisG = chartArea
.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis);
var yaxisG = chartArea
.append("g")
.attr("class", "yAxis")
.call(yAxis);
var linePath = chartArea.append("path")
.datum(data)
.attr("class", "line")
.style("fill", "none")
.style("stroke-width", 2)
.style("stroke", "#6b486b")
.attr("d", line);
if (withTransition) {
linePath.attr("stroke-dasharray", function(d) { return this.getTotalLength(); })
.attr("stroke-dashoffset", function(d) { return this.getTotalLength(); })
.transition()
.duration(750)
.attr("stroke-dashoffset", 0);
}
//// Circles to indiciate the data points
// chartArea.selectAll(".circle")
// .data(data)
// .enter()
// .append("circle")
// .attr("class", ".circle")
// .attr("r", 4)
// .attr("fill", "#fff")
// .style("stroke-width", 2)
// .attr("stroke", "#6b486b")
// .attr("cx", function(d) { return x(d.unit) + x.bandwidth() / 2; })
// .attr("cy", function(d) { return y(d.value); });
}
function pie(data, svg, containerWidth, containerHeight, withTransition) {
var margin = {top: 30, bottom: 30, left: 30, right: 30};
var width = containerWidth - margin.left - margin.right;
var height = containerHeight - margin.top - margin.bottom;
var radius = Math.min(width, height) / 2;
var chartArea = svg
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + (margin.left + width / 2) + ", " + (margin.top + height / 2) + ")");
var color = d3.scaleOrdinal()
.domain(data.map(function(d) { return d.unit; }))
.range(["#98abc5", "#6b486b", "#ff8c00"]);
var pie = d3.pie()
.sort(null)
.value(function(d) { return d.value; });
var arc = d3.arc()
.outerRadius(radius * 0.8)
.innerRadius(0);
var arcPath = chartArea.selectAll(".arc")
.data(pie(data))
.enter()
.append("path")
.style("fill", function(d) { return color(d.data.unit); })
.style("stroke-width", 2)
.style("stroke", "#fff");
if (withTransition) {
arcPath.transition()
.duration(750)
.attrTween("d", tweenArcs);
} else {
arcPath.attr("d", arc);
}
function tweenArcs(d) {
var interpolator = getArcInterpolator(this, d);
return function(t) {
return arc(interpolator(t));
};
}
function getArcInterpolator(el, d) {
// Keep track of the old value by binding to the element
var oldValue = el._oldValue;
var interpolator = d3.interpolate({
startAngle: oldValue ? oldValue.startAngle : 0,
endAngle: oldValue ? oldValue.endAngle : 0
}, d);
// Get the start value and bind that for using it for the next interpolator
el._oldValue = interpolator(0);
return interpolator;
}
}
function bar(data, svg, containerWidth, containerHeight, withTransition) {
var margin = {top: 30, bottom: 50, left: 50, right: 30};
var width = containerWidth - margin.left - margin.right;
var height = containerHeight - margin.top - margin.bottom;
var chartArea = svg
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
// Vertical Bars
var x = d3.scaleBand().range([0, width]).padding(0.1);
var y = d3.scaleLinear().range([height, 0]);
var color = d3.scaleOrdinal()
.domain(data.map(function(d) { return d.unit; }))
.range(["#98abc5", "#6b486b", "#ff8c00"]);
var xAxis = d3.axisBottom().scale(x);
var yAxis = d3.axisLeft().scale(y);
x.domain(data.map(function(d) { return d.unit; }));
y.domain([0, d3.max(data, function(d) { return d.value; })]);
var xaxisG = chartArea
.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis);
var yaxisG = chartArea
.append("g")
.attr("class", "yAxis")
.call(yAxis);
var bars = chartArea.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.unit); })
.attr("width", x.bandwidth())
.style("fill", function(d) { return color(d.unit); });
if (withTransition) {
bars.attr("y", height)
.attr("height", 0)
.transition()
.duration(750)
.delay(function(d, i) { return i * 150; })
.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
} else {
bars.attr("y", function(d) { return y(d.value); })
.attr("height", function(d) { return height - y(d.value); });
}
}
document.querySelector("#bar-button").addEventListener("click", function(){chart(data, "bar", true);});
document.querySelector("#pie-button").addEventListener("click", function(){chart(data, "pie", true);});
document.querySelector("#line-button").addEventListener("click", function(){chart(data, "line", true);});
window.addEventListener("resize", function() {
chart(data, document.querySelector("#chart").dataset.type, false);
});
chart(data, "bar", true);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment