Built with blockbuilder.org
This is an update to the Mike's version by introducing bootstrap and viewbox concept for responsive charts.
xxxxxxxxxx
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.border {
border: 1px solid black;
}
svg {
font-family: sans-serif;
font-size: 10px;
text-anchor: middle;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="border col-md-8">
<div class="bubble-chart">
</div>
</div>
<div class="border col-md-4">
<div class="bubble-chart"></div>
</div>
</div>
<div class="row">
<div class="border col-md-6">
<div class="bubble-chart"></div>
</div>
<div class="border col-md-6">
<div class="bubble-chart"></div>
</div>
</div>
</div>
<script>
var margin = { top:10, right:10, bottom: 10, left:10},
width = 960,
height = 960,
svg = d3.selectAll('.bubble-chart').append('svg')
.attr('width', '100%')
.attr('height', '100%')
.attr('viewBox', '-' + (margin.left + margin.right) + ' ' + (margin.bottom) + ' ' + width + ' ' + height)
.attr('preserveAspectRatio', 'xMinYMin meet');
width = width - margin.left - margin.right;
height = height - margin.top - margin.bottom;
var format = d3.format(',d');
var color = d3.scaleOrdinal(d3.schemeCategory20c);
var pack = d3.pack()
.size([width, height])
.padding(1.5);
d3.csv('./flare.csv', function(d){
d.value = +d.value;
if (d.value) return d;
}, function(error, classes){
if (error) throw error;
var root = d3.hierarchy({children: classes})
.sum(function(d){ return d.value })
.each(function(d){
if (id = d.data.id) {
var id, i = id.lastIndexOf('.');
d.id = id;
d.package = id.slice(0, i);
d.class = id.slice(i+1);
}
});
var node = svg.selectAll('.node')
.data(pack(root).leaves())
.enter()
.append('g')
.attr('class', 'node')
.attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; });
node.append('circle')
.attr('id', function(d){ return d.id; })
.attr('r', function(d){ return d.r; })
.style('fill', function(d){ return color(d.package); });
node.append('clipPath')
.attr('id', function(d){ return 'clip-' + d.id; })
.append('use')
.attr('xlink:href', function(d){ return '#' + d.id; });
node.append('text')
.attr('clip-path', function(d){ return 'url(#clip-' + d.id + ')'; })
.selectAll('tspan')
.data(function(d){ return d.class.split(/(?=[A-Z][^A-Z])/g); })
.enter().append('tspan')
.attr('x', 0)
.attr('y', function(d, i, nodes){ return 13 + (i-nodes.length /2 - 0.5) * 10; })
.text(function(d){ return d; });
node.append('title')
.text(function(d) { return d.id + '\n' + format(d.value); });
});
</script>
</body>
</body>
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.min.js
https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js
https://d3js.org/d3.v4.min.js