Create a gist now

Instantly share code, notes, and snippets.

@lelandlee /README.md
Last active Aug 29, 2015

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="http://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