A recreation of an illustration from this Scientific American article on icon arrays. using the layout function of my d3 icon array plugin
forked from tomgp's block: Welfare spending
xxxxxxxxxx
<html>
<head>
<title>Breakdown of welfare spending</title>
<script src="//d3js.org/d3.v4.0.0-alpha.18.min.js" charset="utf-8"></script>
<script type="text/javascript" src="d3-iconarray.js"></script>
<style type="text/css">
*{
font-family: sans-serif;
color: #333;
}
</style>
</head>
<body>
<h1>Welfare spending</h1>
<div id="gbs-example">
</div>
</body>
<script type="text/javascript">
var data = [
{
label:'State pension',
count:91.6,
colour:'#1E5C92'
},
{
label:'Benefits',
count:66.4,
colour:'#CD842F'
},
{
label:'Tax credits',
count:27.4,
colour:'#5B0F44'
},
{
label:'Pension credit',
count:5.7,
colour:'#039E82'
},{
label:'Jobseekers allowance credit',
count:1.9,
colour:'#B1295E'
},{
label:'Other',
count:23.9,
colour:'#5999D1'
}
];
var layout = d3_iconarray.layout()
.width(50)
.widthFirst(false);
//expand the data to an array
var dataArray = data.reduce(function(value, d){
for(var i=0;i<d.count ;i++){
value.push(d.colour);
}
return value;
}, []);
var grid = layout(dataArray);
var dotRadius = 7;
var width = 800,
height = 600,
margin = {top:20, bottom:20, left:20, right:20 };
var arrayScale = d3.scaleLinear()
.domain([ 0, 50 ])
.range([0, width-(margin.left+margin.right)]);
var svg = d3.select('#gbs-example')
.append('svg')
.attr('width',width)
.attr('height',height)
.append('g')
.attr('transform','translate('+margin.left+','+margin.top+')');
svg.selectAll('circle')
.data(grid)
.enter()
.append('circle')
.attr('cx', function(d){
return arrayScale(d.position.x);
})
.attr('cy', function(d){
return arrayScale(d.position.y);
})
.attr('r',dotRadius)
.attr('fill',function(d){ return d.data; })
d3.select('#gbs-example svg')
.append('g').attr('transform','translate('+ (5*dotRadius)+',' + ( margin.top + 23*dotRadius) + ')')
.selectAll('g.key-element')
.data(data)
.enter()
.append('g')
.attr('transform',function(d,i){ return 'translate(0,'+(i*35)+')'; })
.attr('class','key-element')
.call(function(parent){
parent.append('circle')
.attr('r', dotRadius)
.attr('cx', -dotRadius*2)
.attr('cy', -dotRadius)
.attr('fill', function(d){ return d.colour; })
parent.append('text')
.attr('dx', 0)
.attr('dy',0 )
.text(function(d){
return d.label;
})
.call(wrap, margin.right-20);
})
//wrapping long labels https://bl.ocks.org/mbostock/7555321
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
}
}
});
}
d3.select(self.frameElement).style("height", (height + 200)+"px");
</script>
</html>
https://d3js.org/d3.v4.0.0-alpha.18.min.js