Skip to content

Instantly share code, notes, and snippets.

@bsurnida
Last active June 9, 2017 13:20
Show Gist options
  • Save bsurnida/1842e53ab7fd876d46106aea8c1a8053 to your computer and use it in GitHub Desktop.
Save bsurnida/1842e53ab7fd876d46106aea8c1a8053 to your computer and use it in GitHub Desktop.
It Donut Charts-custom-data
license: mit
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
body {
font-size: 100%;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
width: 960px;
}
#refresh-btn {
float: right;
font-size: 12px;
border-radius: 0;
}
</style>
<body>
<h4>
<a href="http://bl.ocks.org/erichoco/6694616">forked from erichoco/6694616</a>
</h4>
<button type="button" id="refresh-btn">Refresh data</button>
<div id="donut-charts"></div>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
$(function() {
var donutData = genData();
var donuts = new DonutCharts();
donuts.create(donutData);
$('#refresh-btn').on('click', function refresh() {
donuts.update(genData);
});
});
function DonutCharts() {
var charts = d3.select('#donut-charts');
var chart_m,
chart_r,
color = d3.scale.category20();
var getCatNames = function(dataset) {
var catNames = new Array();
for (var i = 0; i < dataset[0].data.length; i++) {
catNames.push(dataset[0].data[i].cat);
}
return catNames;
}
var createLegend = function(catNames) {
var legends = charts.select('.legend')
.selectAll('g')
.data(catNames)
.enter().append('g')
.attr('transform', function(d, i) {
return 'translate(' + (i * 150 + 50) + ', 10)';
});
legends.append('circle')
.attr('class', 'legend-icon')
.attr('r', 6)
.style('fill', function(d, i) {
return color(i);
});
legends.append('text')
.attr('dx', '1em')
.attr('dy', '.3em')
.text(function(d) {
return d;
});
}
var createCenter = function(pie) {
var eventObj = {
'mouseover': function(d, i) {
d3.select(this)
.transition()
.attr("r", chart_r * 0.65);
},
'mouseout': function(d, i) {
d3.select(this)
.transition()
.duration(500)
.ease('bounce')
.attr("r", chart_r * 0.6);
},
'click': function(d, i) {
var paths = charts.selectAll('.clicked');
pathAnim(paths, 0);
paths.classed('clicked', false);
resetAllCenterText();
}
}
var donuts = d3.selectAll('.donut');
// The circle displaying total data.
donuts.append("svg:circle")
.attr("r", chart_r * 0.6)
.style("fill", "#E7E7E7")
.on(eventObj);
donuts.append('text')
.attr('class', 'center-txt type')
.attr('y', chart_r * -0.16)
.attr('text-anchor', 'middle')
.style('font-weight', 'bold')
.text(function(d, i) {
return d.type;
});
donuts.append('text')
.attr('class', 'center-txt value')
.attr('text-anchor', 'middle');
donuts.append('text')
.attr('class', 'center-txt percentage')
.attr('y', chart_r * 0.16)
.attr('text-anchor', 'middle')
.style('fill', '#A2A2A2');
}
var setCenterText = function(thisDonut) {
var sum = d3.sum(thisDonut.selectAll('.clicked').data(), function(d) {
return d.data.val;
});
thisDonut.select('.value')
.text(function(d) {
return (sum)? sum.toFixed(1) + d.unit
: d.total.toFixed(1) + d.unit;
});
thisDonut.select('.percentage')
.text(function(d) {
return (sum)? (sum/d.total*100).toFixed(2) + '%'
: '';
});
}
var resetAllCenterText = function() {
charts.selectAll('.value')
.text(function(d) {
return d.total.toFixed(1) + d.unit;
});
charts.selectAll('.percentage')
.text('');
}
var pathAnim = function(path, dir) {
switch(dir) {
case 0:
path.transition()
.duration(500)
.ease('bounce')
.attr('d', d3.svg.arc()
.innerRadius(chart_r * 0.7)
.outerRadius(chart_r)
);
break;
case 1:
path.transition()
.attr('d', d3.svg.arc()
.innerRadius(chart_r * 0.7)
.outerRadius(chart_r * 1.08)
);
break;
}
}
var updateDonut = function() {
var eventObj = {
'mouseover': function(d, i, j) {
pathAnim(d3.select(this), 1);
var thisDonut = charts.select('.type' + j);
thisDonut.select('.value').text(function(donut_d) {
return d.data.val.toFixed(1) + donut_d.unit;
});
thisDonut.select('.percentage').text(function(donut_d) {
return (d.data.val/donut_d.total*100).toFixed(2) + '%';
});
},
'mouseout': function(d, i, j) {
var thisPath = d3.select(this);
if (!thisPath.classed('clicked')) {
pathAnim(thisPath, 0);
}
var thisDonut = charts.select('.type' + j);
setCenterText(thisDonut);
},
'click': function(d, i, j) {
var thisDonut = charts.select('.type' + j);
if (0 === thisDonut.selectAll('.clicked')[0].length) {
thisDonut.select('circle').on('click')();
}
var thisPath = d3.select(this);
var clicked = thisPath.classed('clicked');
pathAnim(thisPath, ~~(!clicked));
thisPath.classed('clicked', !clicked);
setCenterText(thisDonut);
}
};
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.val;
});
var arc = d3.svg.arc()
.innerRadius(chart_r * 0.7)
.outerRadius(function() {
return (d3.select(this).classed('clicked'))? chart_r * 1.08
: chart_r;
});
// Start joining data with paths
var paths = charts.selectAll('.donut')
.selectAll('path')
.data(function(d, i) {
return pie(d.data);
});
paths
.transition()
.duration(1000)
.attr('d', arc);
paths.enter()
.append('svg:path')
.attr('d', arc)
.style('fill', function(d, i) {
return color(i);
})
.style('stroke', '#FFFFFF')
.on(eventObj)
paths.exit().remove();
resetAllCenterText();
}
this.create = function(dataset) {
var $charts = $('#donut-charts');
chart_m = $charts.innerWidth() / dataset.length / 2 * 0.14;
chart_r = $charts.innerWidth() / dataset.length / 2 * 0.85;
charts.append('svg')
.attr('class', 'legend')
.attr('width', '100%')
.attr('height', 50)
.attr('transform', 'translate(0, -100)');
var donut = charts.selectAll('.donut')
.data(dataset)
.enter().append('svg:svg')
.attr('width', (chart_r + chart_m) * 2)
.attr('height', (chart_r + chart_m) * 2)
.append('svg:g')
.attr('class', function(d, i) {
return 'donut type' + i;
})
.attr('transform', 'translate(' + (chart_r+chart_m) + ',' + (chart_r+chart_m) + ')');
createLegend(getCatNames(dataset));
createCenter();
updateDonut();
}
this.update = function(dataset) {
// Assume no new categ of data enter
var donut = charts.selectAll(".donut")
.data(dataset);
updateDonut();
}
}
/*
* Returns a json-like object.
*/
function genData() {
var type = ['Users', 'Avg Upload', 'Avg Files Shared'];
var unit = ['M', 'GB', ''];
var cat = ['Google Drive', 'Dropbox', 'iCloud', 'OneDrive', 'Box'];
var dataset = new Array();
for (var i = 0; i < type.length; i++) {
var data = new Array();
var total = 0;
for (var j = 0; j < cat.length; j++) {
var value = Math.random()*10*(3-i);
total += value;
data.push({
"cat": cat[j],
"val": value
});
}
dataset.push({
"type": type[i],
"unit": unit[i],
"data": data,
"total": total
});
}
console.log(JSON.stringify(dataset, null, 2));
var customdata=`
[
{
"type": "size",
"unit": "M",
"data": [
{
"cat": "file1",
"val": 10
},
{
"cat": "file2",
"val": 20
}
],
"total": 30
},
{
"type": "Count",
"unit": "GB",
"data": [
{
"cat": "file1",
"val": 30
},
{
"cat": "file2",
"val": 5
}
],
"total": 35
}
]
`;
//return dataset;
return JSON.parse(customdata);
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment