Skip to content

Instantly share code, notes, and snippets.

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

#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. Then with some more math, the x1,x2, y1, and y2 of the individual lines.

The purpose is to be a stacked donut chart, without having to explicitly having multiple paths, instead the chart draws a line whenever there is a break in the data. ActionListeners are added on 'mouseover' and 'mouseout'. Each line of the ray is uniquely tagged so that when a ray is selected all the lines on it are highlighted.

###Next Steps:

  • How to not fake the stacked bar chart by having a multi colour bar?
  • Make the data scale to the dimensions of the chart...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Art - Stacked Lines</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>
var numberOfBars = 80;
create();
function create(){
data = [];
for(var x = 0; x < numberOfBars; x ++){
var val1 = Math.random()*100 + 50
data.push({
value1: val1,
value2: Math.random()*100 + val1
})
}
generateDonut(data)
}
function generateDonut(data){
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 outerRadius = smallestDim / 4.5,
innerRadius = outerRadius / 2;
var pie = d3.layout.pie()
.value(function(d){ return 10; })
.padAngle(.010);
var arc = d3.svg.arc()
.padRadius(outerRadius) //is this line even necessary???
.innerRadius(innerRadius);
var coordinates = [];
var coordinates2 = [];
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.value1 + d.data.value2;
//for the coordinates
var alpha = (d.startAngle + d.endAngle)/2;
var l = d.outerRadius
coordinates.push([alpha, l])
coordinates2.push([alpha, l - d.data.value2])
})
.attr("d", arc)
.style('fill', 'rgba(128,0,0,.2') //change this value to see where the bars should be
.style('stroke', 'none')
.on('mouseover', function(d){
console.log(d)
d3.select(this).style('stroke', 'orange');
d3.select(this).style('stroke-width', '2px');
var target = 'a' + String((d.startAngle + d.endAngle)/2).replace('.','');
d3.selectAll("." + target).style("stroke-width", "5px")
})
.on('mouseout', function(d){
d3.select(this).style('stroke', 'none');
var target = 'a' + String((d.startAngle + d.endAngle)/2).replace('.','');
d3.selectAll("." + target).style("stroke-width", "2.5px")
})
drawLines(coordinates, 'maroon', 'outer-bar');
drawLines(coordinates2, 'black', 'inner-bar');
function drawLines(coordinates, colour, group){
coordinates = coordinates.sort(function(a, b){
return a[0] - b[0];
})
for(i in coordinates){
var alpha = coordinates[i][0];
var l = coordinates[i][1];
var x0 = l * Math.sin(alpha);
var y0 = l * Math.cos(alpha);
//find tangental line
var newAngle = alpha + Math.PI/2;
var newl = l * Math.PI / numberOfBars;
var x2 = x0 + newl * Math.sin(newAngle)
var y2 = y0 + newl * Math.cos(newAngle)
var x1 = x0 - newl * Math.sin(newAngle)
var y1 = y0 - newl * Math.cos(newAngle)
var target = 'a' + String(alpha).replace('.','');
svg.append("line")
.style("stroke-width", "2.5px")
.style("stroke", colour)
.attr("class", target + " " + group)//assigning multiple classes
.attr("x1", x1)
.attr("x2", x2)
.attr("y1", -y1)
.attr("y2", -y2)
.on('mouseover', function(d){
//'d' doesnt reference anything as there is no associated data
console.log(this)
d3.selectAll('.' + group).style("stroke-width", "5px")
})
.on('mouseout', function(d){
d3.selectAll('.' + group).style("stroke-width", "2.5px")
})
}
}
}
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