Skip to content

Instantly share code, notes, and snippets.

@lsquaredleland
Last active August 14, 2016 08:52
Show Gist options
  • Save lsquaredleland/e50859751f3b096e3b27 to your computer and use it in GitHub Desktop.
Save lsquaredleland/e50859751f3b096e3b27 to your computer and use it in GitHub Desktop.
Isotype Donut Art?

#Isotype Art Maybe? To create this 'visualisation' I started with a donut chart, where that outerRadius's would not be consistant. Meaning that they had different values as seen in the foreground. From there, using the angle of the bar relative to the x-axis and the length of the outer radius, I calculated the x and y coordinates of bar's end. Which was then used to calculate the locations for the invidividual circles.

###To Consider:

  • Add ClipPaths
  • Improve scaling with different number of bars, does not work perfectly currently.
  • How to bind data to the isotype more formally?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>IsoType Donut Art?</title>
<script src="https://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="chartArea">
</div>
<script src="main_donut.js"></script>
</body>
</html>
//Adding clipPath to the end circle
create();
function create(){
var num_bars = 80;
data = [];
for(var x = 0; x < num_bars; x ++){
data.push(Math.random()*200 + 150 )
}
generateDonut(data, num_bars)//data is used to generate height of invisible bars
}
function generateDonut(data, num_bars){
var divH = parseInt( d3.select("#chartArea").style("height") );
var divW = parseInt( d3.select("#chartArea").style("width") );
var margin = {top: 10, right: 10, bottom: 10, left: 10};
var w = divW - margin.left - margin.right;
h = divH - margin.top - margin.bottom;
smallestDim = h < w ? h : w;
var rad_mult = .028*80/num_bars; //this is dependent on length of bar
var stroke_width = .5;
var outerRadius = smallestDim / 4.5,
innerRadius = outerRadius / 2;
var pie = d3.layout.pie()
.value(function(d){ return 10; })
.padAngle(.007);
var arc = d3.svg.arc()
//.padRadius(outerRadius)
.innerRadius(innerRadius);
var lines = [];
var valueline = d3.svg.line()
.interpolate("step-after") //step-after looks cool
.x(function(d) { return d[0]; })
.y(function(d) { return d[1]; });
var svg = d3.select("#chartArea").append("svg")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("transform", "translate(" + w / 2 + "," + (h) / 2 + ")");
svg.selectAll("path")
.data(pie(data))
.enter().append("path")
.each(function(d) {
d.outerRadius = innerRadius + d.data;
//for the lines
var alpha = (d.startAngle + d.endAngle)/2;
var l = d.outerRadius
lines.push([alpha, l])
})
.attr("d", arc)
.style('fill', 'lightblue') //change this value to see where the bars should be
.style('stroke', 'none');
drawCircle(lines)
function drawCircle(lines){
var colourScale = d3.scale.category20b()
for(i in lines){
var alpha = lines[i][0];
for(var l = innerRadius + innerRadius*rad_mult; l <= lines[i][1] + l*rad_mult; l += l*rad_mult*2.05 + 2*stroke_width){
//starts at the innerRadius and moves outwards
var x = l * Math.sin(alpha)
var y = l * Math.cos(alpha)
//how to bind data to this?
//use an 'random name' element???? to bind directly to the element?
//how to use data() in this case?
svg.append("circle")
.style('stroke', 'maroon')
.style('stroke-width', stroke_width)//taken account for in terms of spacing
.style("fill", colourScale(i))
.attr('cx', x)
.attr('cy', -y)
.attr('r', l*rad_mult)
//hacky way to bind data? what should it be called?
.attr('d1', 'put the #of circle out of total')
.attr('d2', (l-innerRadius)/(lines[i][1]-innerRadius))
.on('mouseover', function(d){
d3.select(this).style('fill', 'white');
d3.select(this).style('stroke', 'black');
})
.on('click', function(d){
console.log(this);
})
}
}
}
}
body{
background-color: rgba(235, 232, 193, 0.24902);
}
#chartArea {
border: 2px dashed black;
height: 1000px;
width: 1000px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment