Created
January 3, 2018 06:01
-
-
Save Zhenmao/554e595e9f4b200ed17724d71039216e to your computer and use it in GitHub Desktop.
Bar, pie and line charts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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