Built with blockbuilder.org
xxxxxxxxxx
<html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.buttons {
margin: 40px;
}
circle {
fill: rgb(0, 153, 255);
fill-opacity: 0.25;
stroke: rgb(177, 208, 229);
stroke-width: 4px;
}
text {
text-anchor: middle;
font-family: sans-serif;
}
</style>
</head>
<body>
<div class="container">
<div class="buttons">
<input type="radio" id="calories" name="property" value="calories" onclick="bubbleChart('calories')">
<label for="calories">Calories</label>
<input type="radio" id="protein" name="property" value="protein" onclick="bubbleChart('protein')">
<label for="protein">Protein</label>
<input type="radio" id="fat" name="property" value="fat" onclick="bubbleChart('fat')">
<label for="fat">Fat</label>
<input type="radio" id="sodium" name="property" value="sodium" onclick="bubbleChart('sodium')">
<label for="sodium">Sodium</label>
<input type="radio" id="fiber" name="property" value="fiber" onclick="bubbleChart('fiber')">
<label for="fiber">Fiber</label>
<input type="radio" id="carbohydrates" name="property" value="carbohydrates" onclick="bubbleChart('carbohydrates')">
<label for="carbohydrates">Carbohydrates</label>
<input type="radio" id="sugars" name="property" value="sugars" onclick="bubbleChart('sugars')">
<label for="sugars">Sugars</label>
<input type="radio" id="potassium" name="property" value="potassium" onclick="bubbleChart('potassium')">
<label for="potassium">Potassium</label>
<input type="radio" id="vitamins" name="property" value="vitamins" onclick="bubbleChart('vitamins')">
<label for="vitamins">Vitamins</label>
</div>
<div class="visual">
</div>
</div>
<script>
let width = window.innerWidth;
let height = window.innerHeight;
let svg = d3.select('.visual').append('svg')
.attr('width', width)
.attr('height', height);
function bubbleChart(property) {
let pack = d3.pack()
.size([width, height])
.padding(8);
let units = ['', '', 'g', 'g', 'mg', 'g', 'g', 'g', 'mg', '%']
let duration = 1000;
let delay = 10;
d3.csv('cereal.csv', function(d) {
if (!isNaN(parseFloat(d[property])) && isFinite(d[property])){
d[property] = +d[property];
} else {
throw 'Property value isn\'t a number or doesn\'t exist';
}
return d;
}, function(error, objects) {
if (error) throw error;
let index = objects.columns.indexOf(property)
let root = d3.hierarchy({children: objects})
.sum(d => d[property])
.sort((a, b) => b.value - a.value);
let nodes = svg.selectAll('.node').data([]).exit().remove();
nodes = svg.selectAll('.node')
.data(pack(root).leaves())
.enter().append('g')
.attr('class', 'node')
.attr('transform', d => 'translate(' + d.x + ',' + d.y + ')');
nodes.append('title')
.text(d => '\"' + d.data.name + '\"\n'
+ property.replace(property[0], l => l.toUpperCase())
+ ': ' + d.value + units[index]);
nodes.append('circle')
.transition()
.duration(duration)
.delay((d, i) => i * delay)
.attr('r', d => d.r);
nodes.append("text")
.transition()
.duration(duration)
.delay((d, i) => i * delay)
.attr('font-size', (d) => d.r / 5)
.text(d => d.data.name.substring(0, d.r / 3));
});
}
bubbleChart('calories');
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js