Skip to content

Instantly share code, notes, and snippets.

@bytesbysophie
Last active November 17, 2019 17:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bytesbysophie/feea36aaf20091c281d1c6a1122642e5 to your computer and use it in GitHub Desktop.
Save bytesbysophie/feea36aaf20091c281d1c6a1122642e5 to your computer and use it in GitHub Desktop.
Bubble Chart
license: mit
<!DOCTYPE html>
<h1>WHAT WOULD YOU PAY FOR?</h1>
<h2>If you could only have one media subscription for the next year</b>, which would you have?</h2>
<svg width="960" height="550"></svg>
<p class="reference">Source: http://www.digitalnewsreport.org/survey/2019/paying-for-news-and-the-limits-of-subscription/</p>
<style>
.bubble-label, text, h1, h2, p {
font-family: Helvetica;
}
.bubble-label, text, h1 {
fill: gray;
font-weight:500;
font-size: 14px;
}
text {
font-size: 12px;
}
.reference {
font-size: 12px;
color: gray;
}
h1,h2 {
font-size: 14px;
font-weight: 500;
color: gray;
}
h2{
font-size: 20px;
}
.domain {
stroke: None;
}
</style>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
// Source: http://www.digitalnewsreport.org/survey/2019/paying-for-news-and-the-limits-of-subscription/
const data = [
{index: 0, label: 'News', over45: 15, under45: 7},
{index: 1, label: 'Video streaming', over45: 22, under45: 37},
{index: 2, label: 'Music streaming', over45: 8, under45: 15},
{index: 3, label: 'Sport', over45: 8, under45: 7},
{index: 4, label: 'Online gaming', over45: 1, under45: 7},
{index: 5, label: 'Storage', over45: 5, under45: 5},
{index: 6, label: 'Online dating', over45: 1, under45: 3},
{index: 7, label: 'Nothing', over45: 40, under45: 20}
]
var svg = d3.select("svg"),
margin = {top: 100, right: 40, bottom: 100, left: 80, axis: 20},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom - margin.axis * 2,
g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleBand().rangeRound([0, width]).padding(0.1);
var y = d3.scaleLinear().rangeRound([height, 0]);
var r_o45 = d3.scaleLinear().rangeRound([0, height]);
var r_u45 = d3.scaleLinear().rangeRound([0, height]);
var xAxis = d3.axisBottom(x).tickSize([]).tickPadding(10);
x.domain(data.map(d => { return d.label; }));
y.domain([d3.min(data, d => {return Number(-d.under45);}),
d3.max(data, d => {return Number(d.over45);})]);
r_o45.domain([0, d3.max(data, function(d) {
return Number(d.over45) * 4;
})])
r_u45.domain([0, d3.max(data, function(d) {
return Number(d.under45) * 4;
})])
// Append x axis
g.append('g')
.attr("transform", "translate(" + -50 + "," + height/2 + ")")
.call(xAxis);
// Place labels in vertical center
g.selectAll(".tick").selectAll("text").attr('dy', '0.em')
// Append top circles
g.selectAll(".circle-top")
.data(data)
.enter().append("circle")
.attr("class", "circle-top")
.attr('cx', function(d) { return x(d.label); })
.attr('cy', function(d) { return y(d.over45) - margin.axis; })
.attr('r', function(d) { return r_o45(d.over45); })
.attr('fill', "#fc9bca")
// Append bottom circles
g.selectAll(".circle-bottom")
.data(data)
.enter().append("circle")
.attr("class", "circle-bottom")
.attr('cx', function(d) { return x(d.label); })
.attr('cy', function(d) { return y(-d.under45) + margin.axis; })
.attr('r', function(d) { return r_u45(d.under45); })
.attr('fill', "#043d6b")
// Append top lines
g.selectAll(".line-top")
.data(data)
.enter().append("line")
.attr("class", "line-top")
.attr("x1", function(d) { return x(d.label); })
.attr("y1", function(d) { return y(0) - margin.axis; })
.attr("x2", function(d) { return x(d.label); })
.attr("y2", function(d) { return y(d.over45) + r_o45(d.over45) - margin.axis; })
.attr("stroke", "grey")
.style("stroke-dasharray", ("3, 3"));
// Append bottom lines
g.selectAll(".line-bottom")
.data(data)
.enter().append("line")
.attr("class", "line-bottom")
.attr("x1", function(d) { return x(d.label); })
.attr("y1", function(d) { return y(0) + margin.axis; })
.attr("x2", function(d) { return x(d.label); })
.attr("y2", function(d) { return y(-d.under45) - r_u45(d.under45) + margin.axis; })
.attr("stroke", "grey")
.style("stroke-dasharray", ("3, 3"));
// Append top labels
g.selectAll(".bubble-label-top")
.data(data)
.enter().append("text")
.attr("class", "bubble-label-top")
.attr("x", function(d) { return x(d.label) - 3; })
.attr('y', function(d) { return y(d.over45) - margin.axis; })
.attr("dy", d => {
dist = 0.35
if(d.over45 < 9) return dist-r_o45(d.over45)/12-0.9 + "em"
else return ".35em"
})
.attr("dx", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.over45 + " %"; });
// Append bottom labels
g.selectAll(".bubble-label-bottom")
.data(data)
.enter().append("text")
.attr("class", "bubble-label-bottom")
.attr("x", function(d) { return x(d.label) - 3; })
.attr('y', function(d) { return y(-d.under45) + margin.axis; })
.attr("dy", d => {
dist = 0.35
if(d.under45 < 9) return dist+r_u45(d.under45)/12+0.9 + "em"
else return ".35em"
})
.attr("dx", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.under45 + " %"; });
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment