Pie Chart with Zoomable sectors and tooltips
forked from arpitnarechania's block: Pie Chart
license: MIT |
Pie Chart with Zoomable sectors and tooltips
forked from arpitnarechania's block: Pie Chart
<!DOCTYPE> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Pie Chart</title> | |
<!-- JavaScript Libraries //--> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<!-- CSS Style //--> | |
<link href="style.css" rel="stylesheet" type="text/css"> | |
<script type="text/javascript"> | |
function renderPieChart (dataset,dom_element_to_append_to, colorScheme){ | |
var margin = {top:50,bottom:50,left:50,right:50}; | |
var width = 500 - margin.left - margin.right, | |
height = width, | |
radius = Math.min(width, height) / 2; | |
var donutWidth = 75; | |
var legendRectSize = 18; | |
var legendSpacing = 4; | |
dataset.forEach(function(item){ | |
item.enabled = true; | |
}); | |
var color = d3.scaleOrdinal() | |
.range(colorScheme); | |
var svg = d3.select(dom_element_to_append_to) | |
.append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.append("g") | |
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); | |
var arc = d3.arc() | |
.outerRadius(radius - 10) | |
.innerRadius(radius - donutWidth); | |
var pie = d3.pie() | |
.sort(null) | |
.value(function(d) { return d.value; }); | |
var tooltip = d3.select(dom_element_to_append_to) | |
.append('div') | |
.attr('class', 'tooltip'); | |
tooltip.append('div') | |
.attr('class', 'label'); | |
tooltip.append('div') | |
.attr('class', 'count'); | |
tooltip.append('div') | |
.attr('class', 'percent'); | |
var path = svg.selectAll('path') | |
.data(pie(dataset)) | |
.enter() | |
.append('path') | |
.attr('d', arc) | |
.attr('fill', function(d, i) { | |
return color(d.data.label); | |
}) | |
.each(function(d) { this._current = d; }); | |
path.on('mouseover', function(d) { | |
var total = d3.sum(dataset.map(function(d) { | |
return (d.enabled) ? d.value : 0; | |
})); | |
var percent = Math.round(1000 * d.data.value / total) / 10; | |
tooltip.select('.label').html(d.data.label.toUpperCase()).style('color','black'); | |
tooltip.select('.count').html(d.data.value); | |
tooltip.select('.percent').html(percent + '%'); | |
tooltip.style('display', 'block'); | |
tooltip.style('opacity',2); | |
}); | |
path.on('mousemove', function(d) { | |
tooltip.style('top', (d3.event.layerY + 10) + 'px') | |
.style('left', (d3.event.layerX - 25) + 'px'); | |
}); | |
path.on('mouseout', function() { | |
tooltip.style('display', 'none'); | |
tooltip.style('opacity',0); | |
}); | |
var legend = svg.selectAll('.legend') | |
.data(color.domain()) | |
.enter() | |
.append('g') | |
.attr('class', 'legend') | |
.attr('transform', function(d, i) { | |
var height = legendRectSize + legendSpacing; | |
var offset = height * color.domain().length / 2; | |
var horz = -5 * legendRectSize; | |
var vert = i * height - offset; | |
return 'translate(' + horz + ',' + vert + ')'; | |
}); | |
legend.append('rect') | |
.attr('width', legendRectSize) | |
.attr('height', legendRectSize) | |
.style('fill', color) | |
.style('stroke', color) | |
.on('click', function(label) { | |
var rect = d3.select(this); | |
var enabled = true; | |
var totalEnabled = d3.sum(dataset.map(function(d) { | |
return (d.enabled) ? 1 : 0; | |
})); | |
if (rect.attr('class') === 'disabled') { | |
rect.attr('class', ''); | |
} else { | |
if (totalEnabled < 2) return; | |
rect.attr('class', 'disabled'); | |
enabled = false; | |
} | |
pie.value(function(d) { | |
if (d.label === label) d.enabled = enabled; | |
return (d.enabled) ? d.value : 0; | |
}); | |
path = path.data(pie(dataset)); | |
path.transition() | |
.duration(750) | |
.attrTween('d', function(d) { | |
var interpolate = d3.interpolate(this._current, d); | |
this._current = interpolate(0); | |
return function(t) { | |
return arc(interpolate(t)); | |
}; | |
}); | |
}); | |
legend.append('text') | |
.attr('x', legendRectSize + legendSpacing) | |
.attr('y', legendRectSize - legendSpacing) | |
.text(function(d) { return d; }) | |
}; | |
</script> | |
</head> | |
<body> | |
<div style="margin:75px;" id="chart"></div> | |
</body> | |
<script> | |
var inputData = [ | |
{label:"Beijing Baidu Netcom Sci And Tec",value:81}, | |
{label:"Baidu Online Network Tech Beijing Co Ltd",value:39}, | |
{label:"Zhuji Yuebo Enterprise Man Consultation Co Ltd",value:7}, | |
{label:"Cangnan Boya Tech Co Ltd",value:81}, | |
{label:"Zhong Gaoming",value:81} | |
] | |
var colorScheme = ["#8CE984","#FF7474","#59D1FF","#FFA45C","#B75CFF"]; | |
renderPieChart(inputData,"#chart",colorScheme); | |
</script> | |
</html> |
/* Function: renderPieChart | |
* Variables: | |
* * dataset: contains the input data for plotting the pie chart, | |
* input should be in the form of array of objects where each object should be like {label: , value: } | |
* * dom_element_to_append_to : class name of the div element where the graph have to be appended | |
* Contains transitions and hover effects, load the css file 'css/pieChart.css' at the top of html page where the pie chart has to be loaded | |
*/ | |
function renderPieChart (dataset,dom_element_to_append_to, colorScheme){ | |
var margin = {top:50,bottom:50,left:50,right:50}; | |
var width = 500 - margin.left - margin.right, | |
height = width, | |
radius = Math.min(width, height) / 2; | |
var donutWidth = 75; | |
var legendRectSize = 18; | |
var legendSpacing = 4; | |
dataset.forEach(function(item){ | |
item.enabled = true; | |
}); | |
var color = d3.scaleOrdinal() | |
.range(colorScheme); | |
var svg = d3.select(dom_element_to_append_to) | |
.append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.append("g") | |
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); | |
var arc = d3.svg.arc() | |
.outerRadius(radius - 10) | |
.innerRadius(radius - donutWidth); | |
var pie = d3.layout.pie() | |
.sort(null) | |
.value(function(d) { return d.value; }); | |
var tooltip = d3.select(dom_element_to_append_to) | |
.append('div') | |
.attr('class', 'tooltip'); | |
tooltip.append('div') | |
.attr('class', 'label'); | |
tooltip.append('div') | |
.attr('class', 'count'); | |
tooltip.append('div') | |
.attr('class', 'percent'); | |
var path = svg.selectAll('path') | |
.data(pie(dataset)) | |
.enter() | |
.append('path') | |
.attr('d', arc) | |
.attr('fill', function(d, i) { | |
return color(d.data.label); | |
}) | |
.each(function(d) { this._current = d; }); | |
path.on('mouseover', function(d) { | |
var total = d3.sum(dataset.map(function(d) { | |
return (d.enabled) ? d.value : 0; | |
})); | |
var percent = Math.round(1000 * d.data.value / total) / 10; | |
tooltip.select('.label').html(d.data.label.toUpperCase()).style('color','black'); | |
tooltip.select('.count').html(d.data.value); | |
tooltip.select('.percent').html(percent + '%'); | |
tooltip.style('display', 'block'); | |
tooltip.style('opacity',2); | |
}); | |
path.on('mousemove', function(d) { | |
tooltip.style('top', (d3.event.layerY + 10) + 'px') | |
.style('left', (d3.event.layerX - 25) + 'px'); | |
}); | |
path.on('mouseout', function() { | |
tooltip.style('display', 'none'); | |
tooltip.style('opacity',0); | |
}); | |
var legend = svg.selectAll('.legend') | |
.data(color.domain()) | |
.enter() | |
.append('g') | |
.attr('class', 'legend') | |
.attr('transform', function(d, i) { | |
var height = legendRectSize + legendSpacing; | |
var offset = height * color.domain().length / 2; | |
var horz = -2 * legendRectSize; | |
var vert = i * height - offset; | |
return 'translate(' + horz + ',' + vert + ')'; | |
}); | |
legend.append('rect') | |
.attr('width', legendRectSize) | |
.attr('height', legendRectSize) | |
.style('fill', color) | |
.style('stroke', color) | |
.on('click', function(label) { | |
var rect = d3.select(this); | |
var enabled = true; | |
var totalEnabled = d3.sum(dataset.map(function(d) { | |
return (d.enabled) ? 1 : 0; | |
})); | |
if (rect.attr('class') === 'disabled') { | |
rect.attr('class', ''); | |
} else { | |
if (totalEnabled < 2) return; | |
rect.attr('class', 'disabled'); | |
enabled = false; | |
} | |
pie.value(function(d) { | |
if (d.label === label) d.enabled = enabled; | |
return (d.enabled) ? d.value : 0; | |
}); | |
path = path.data(pie(dataset)); | |
path.transition() | |
.duration(750) | |
.attrTween('d', function(d) { | |
var interpolate = d3.interpolate(this._current, d); | |
this._current = interpolate(0); | |
return function(t) { | |
return arc(interpolate(t)); | |
}; | |
}); | |
}); | |
legend.append('text') | |
.attr('x', legendRectSize + legendSpacing) | |
.attr('y', legendRectSize - legendSpacing) | |
.text(function(d) { return d; }) | |
}; |
.tooltip { | |
background: #eee; | |
box-shadow: 0 0 5px #999999; | |
color: #333; | |
font-size: 12px; | |
left: 130px; | |
padding: 10px; | |
position: absolute; | |
text-align: center; | |
top: 95px; | |
width: 80px; | |
z-index: 10; | |
display: block; | |
opacity: 0; | |
} | |
.legend { | |
font-size: 12px; | |
} | |
rect { | |
cursor: pointer; /* NEW */ | |
stroke-width: 2; | |
} | |
rect.disabled { /* NEW */ | |
fill: transparent !important; /* NEW */ | |
} |