Last active
August 29, 2015 14:03
-
-
Save nitaku/92eb6fa2412af3270053 to your computer and use it in GitHub Desktop.
Pie vs. pie III
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### polar layout ### | |
polar = () -> | |
# defaults | |
#scale = d3.scale.linear | |
angle = null | |
self = (data) -> | |
angle = 2*Math.PI/data.length | |
data.forEach (d, i) -> | |
d.angle = if data.length > 2 then i * angle else (i-0.25) * angle | |
return data | |
self.angle = () -> | |
return angle | |
return self | |
### --- ### | |
rand2_6 = () -> 2 + Math.round(Math.random() * 6) | |
data = d3.range(rand2_6()).map (d) -> { category: "cat_#{d}", value: Math.random() } | |
console.log data | |
max = d3.max(data, (d) -> d.value) | |
width = 960 | |
height = 500 | |
side = Math.min(width,height) | |
RADIUS = side / 4 - 20 | |
polar_layout = polar() | |
polar_data = polar_layout(data) | |
console.log polar_data | |
svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.append('g') | |
.attr | |
transform: "translate(#{width/2}, #{height/2})" | |
ul = svg.append("g") | |
.attr | |
transform: "translate(#{-side/2}, #{-side/4})" | |
um = svg.append("g") | |
.attr | |
transform: "translate(0, #{-side/4})" | |
ur = svg.append("g") | |
.attr | |
transform: "translate(#{+side/2}, #{-side/4})" | |
bl = svg.append("g") | |
.attr | |
transform: "translate(#{-side/2}, #{+side/4})" | |
bm = svg.append("g") | |
.attr | |
transform: "translate(0, #{+side/4})" | |
br = svg.append("g") | |
.attr | |
transform: "translate(#{+side/2}, #{+side/4})" | |
color = d3.scale.ordinal() | |
.range(["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"]) | |
# pie chart | |
pie = d3.layout.pie() | |
.sort(null) | |
.value((d) -> d.value ) | |
arc_generator = d3.svg.arc() | |
.innerRadius(0) | |
.outerRadius(RADIUS) | |
ul.selectAll('.arc') | |
.data(pie(data)) | |
.enter().append('path') | |
.attr | |
class: 'arc' | |
d: arc_generator | |
fill: (d, i) -> color(i) | |
# arc chart subplotting | |
radius_scale = d3.scale.linear() | |
.domain([0, max]) | |
.range([0, RADIUS]) | |
inner_radius_scale = d3.scale.linear() | |
.domain([0, max]) | |
.range([RADIUS*0.4, RADIUS]) | |
arc_generator = d3.svg.arc() | |
.innerRadius((d) -> inner_radius_scale(max-d.value)) | |
.outerRadius((d) -> radius_scale(max)) | |
.startAngle((d) -> d.angle - polar_layout.angle()/2) | |
.endAngle((d) -> d.angle + polar_layout.angle()/2) | |
pies = um.selectAll('.arc') | |
.data(polar_data) | |
pies.enter().append('path') | |
.attr | |
class: 'arc' | |
d: arc_generator | |
fill: (count, klass) -> color(klass) | |
# radar chart | |
#outer_polygon_generator = d3.svg.line() | |
# .x((d) -> RADIUS*Math.cos(d.angle-Math.PI/2)) | |
# .y((d) -> RADIUS*Math.sin(d.angle-Math.PI/2)) | |
# | |
#ur.append("path") | |
# .datum(polar_data) | |
# .attr | |
# class: 'outer_polygon' | |
# d: (ds) -> outer_polygon_generator(ds) + 'z' | |
# | |
#ur.selectAll(".radius") | |
# .data(polar_data) | |
# .enter().append("path") | |
# .attr('class','radius') | |
# .attr("d", (d) -> "M0 0 L#{RADIUS*Math.cos(d.angle-Math.PI/2)} #{RADIUS*Math.sin(d.angle-Math.PI/2)}") | |
# | |
#polygon_generator = d3.svg.line() | |
# .x((d) -> RADIUS/max*d.value*Math.cos(d.angle-Math.PI/2)) | |
# .y((d) -> RADIUS/max*d.value*Math.sin(d.angle-Math.PI/2)) | |
# | |
#ur.append('path') | |
# .datum(polar_data) | |
# .attr | |
# class: 'polygon' | |
# d: (ds) -> polygon_generator(ds) + 'z' | |
# | |
#ur.selectAll(".dot") | |
# .data(polar_data) | |
# .enter().append("circle") | |
# .attr('class','dot') | |
# .attr | |
# cx: (d) -> "#{RADIUS/max*d.value*Math.cos(d.angle-Math.PI/2)}" | |
# cy: (d) -> "#{RADIUS/max*d.value*Math.sin(d.angle-Math.PI/2)}" | |
# r: 4 | |
# fill: (d, i) -> color(i) | |
# bubble chart | |
max_dist = RADIUS / (1+Math.sin(polar_layout.angle()/2)) | |
dist_scale = d3.scale.sqrt() | |
.domain([0, max]) | |
.range([0, max_dist]) | |
bm.selectAll('.bubble') | |
.data(polar_data) | |
.enter().append('circle') | |
.attr | |
class: 'bubble' | |
cx: (d) -> dist_scale(d.value)*Math.cos(d.angle-Math.PI/2) | |
cy: (d) -> dist_scale(d.value)*Math.sin(d.angle-Math.PI/2) | |
r: (d) -> dist_scale(d.value)*Math.sin(polar_layout.angle()/2) | |
fill: (d, i) -> color(i) | |
#bm.append('circle') | |
# .attr | |
# r: RADIUS | |
# fill: 'none' | |
# stroke: 'black' | |
# 'stroke-dasharray': '1 3' | |
# | |
#bm.append('circle') | |
# .attr | |
# r: max_dist | |
# fill: 'none' | |
# stroke: 'black' | |
# 'stroke-dasharray': '1 3' | |
# polar area chart | |
radius_scale = d3.scale.sqrt() | |
.domain([0, max]) | |
.range([0, RADIUS]) | |
arc_generator = d3.svg.arc() | |
.innerRadius(0) | |
.outerRadius((d) -> radius_scale(d.value)) | |
.startAngle((d) -> d.angle - polar_layout.angle()/2) | |
.endAngle((d) -> d.angle + polar_layout.angle()/2) | |
bl.selectAll('.arc') | |
.data(polar_data) | |
.enter().append('path') | |
.attr | |
class: 'arc' | |
d: arc_generator | |
fill: (d, i) -> color(i) | |
# flower chart | |
max_dist = RADIUS / (1+Math.sin(polar_layout.angle()/2)) | |
dist_scale = d3.scale.sqrt() | |
.domain([0, max]) | |
.range([0, max_dist]) | |
br.selectAll('.petal') | |
.data(polar_data) | |
.enter().append('path') | |
.attr | |
class: 'petal' | |
d: (d) -> | |
r = dist_scale(d.value) * Math.sin(polar_layout.angle()/2) | |
l = dist_scale(d.value) * Math.cos(polar_layout.angle()/2) | |
theta = d.angle-Math.PI/2 | |
if l is 0 | |
# degenerate case (circles are tangent to each other) | |
far_x = (dist_scale(d.value)+r) * Math.cos(theta) | |
far_y = (dist_scale(d.value)+r) * Math.sin(theta) | |
return "M0 0 A#{r} #{r} 0 1 1 #{far_x} #{far_y} A#{r} #{r} 0 1 1 0 0" | |
theta_a = theta - polar_layout.angle()/2 | |
theta_b = theta + polar_layout.angle()/2 | |
return "M0 0 L#{l*Math.cos(theta_a)} #{l*Math.sin(theta_a)} A#{r} #{r} 0 1 1 #{l*Math.cos(theta_b)} #{l*Math.sin(theta_b)} z" | |
fill: (d, i) -> color(i) | |
# stick chart | |
W = 8 | |
dist_scale = d3.scale.linear() | |
.domain([0, max]) | |
.range([0, RADIUS]) | |
ur.selectAll('.stick') | |
.data(polar_data) | |
.enter().append('path') | |
.attr | |
class: 'stick' | |
d: (d) -> | |
theta = d.angle | |
delta = W/2 / Math.tan(polar_layout.angle()/2) | |
nx = delta*Math.sin(theta) | |
ny = -delta*Math.cos(theta) | |
b_x = nx - W/2*Math.cos(theta) | |
b_y = ny - W/2*Math.sin(theta) | |
e_x = nx + W/2*Math.cos(theta) | |
e_y = ny + W/2*Math.sin(theta) | |
fx = dist_scale(d.value)*Math.sin(theta) | |
fy = -dist_scale(d.value)*Math.cos(theta) | |
c_x = fx - W/2*Math.cos(theta) | |
c_y = fy - W/2*Math.sin(theta) | |
d_x = fx + W/2*Math.cos(theta) | |
d_y = fy + W/2*Math.sin(theta) | |
return "M0 0 L#{b_x} #{b_y} L#{c_x} #{c_y} L#{d_x} #{d_y} L#{e_x} #{e_y} z" | |
fill: (d, i) -> color(i) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
svg { | |
background-color: white; | |
} | |
.arc, .bubble, .petal, .stick { | |
stroke-width: 1; | |
stroke: white; | |
stroke-linejoin: round; | |
} | |
.radius { | |
stroke: gray; | |
stroke-dasharray: 3 3; | |
} | |
.polygon { | |
fill: #DDD; | |
fill-opacity: 0.5; | |
stroke: gray; | |
} | |
.outer_polygon { | |
fill: none; | |
stroke: gray; | |
stroke-dasharray: 3 3; | |
} | |
.dot { | |
stroke: white; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="description" content="Pie vs. pie III" /> | |
<title>Pie vs. pie III</title> | |
<link rel="stylesheet" href="index.css"> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
</head> | |
<body> | |
<script src="index.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* polar layout | |
*/ | |
(function() { | |
var RADIUS, W, arc_generator, bl, bm, br, color, data, dist_scale, height, inner_radius_scale, max, max_dist, pie, pies, polar, polar_data, polar_layout, radius_scale, rand2_6, side, svg, ul, um, ur, width; | |
polar = function() { | |
var angle, self; | |
angle = null; | |
self = function(data) { | |
angle = 2 * Math.PI / data.length; | |
data.forEach(function(d, i) { | |
return d.angle = data.length > 2 ? i * angle : (i - 0.25) * angle; | |
}); | |
return data; | |
}; | |
self.angle = function() { | |
return angle; | |
}; | |
return self; | |
}; | |
/* --- | |
*/ | |
rand2_6 = function() { | |
return 2 + Math.round(Math.random() * 6); | |
}; | |
data = d3.range(rand2_6()).map(function(d) { | |
return { | |
category: "cat_" + d, | |
value: Math.random() | |
}; | |
}); | |
console.log(data); | |
max = d3.max(data, function(d) { | |
return d.value; | |
}); | |
width = 960; | |
height = 500; | |
side = Math.min(width, height); | |
RADIUS = side / 4 - 20; | |
polar_layout = polar(); | |
polar_data = polar_layout(data); | |
console.log(polar_data); | |
svg = d3.select("body").append("svg").attr("width", width).attr("height", height).append('g').attr({ | |
transform: "translate(" + (width / 2) + ", " + (height / 2) + ")" | |
}); | |
ul = svg.append("g").attr({ | |
transform: "translate(" + (-side / 2) + ", " + (-side / 4) + ")" | |
}); | |
um = svg.append("g").attr({ | |
transform: "translate(0, " + (-side / 4) + ")" | |
}); | |
ur = svg.append("g").attr({ | |
transform: "translate(" + (+side / 2) + ", " + (-side / 4) + ")" | |
}); | |
bl = svg.append("g").attr({ | |
transform: "translate(" + (-side / 2) + ", " + (+side / 4) + ")" | |
}); | |
bm = svg.append("g").attr({ | |
transform: "translate(0, " + (+side / 4) + ")" | |
}); | |
br = svg.append("g").attr({ | |
transform: "translate(" + (+side / 2) + ", " + (+side / 4) + ")" | |
}); | |
color = d3.scale.ordinal().range(["#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", "#e6ab02", "#a6761d", "#666666"]); | |
pie = d3.layout.pie().sort(null).value(function(d) { | |
return d.value; | |
}); | |
arc_generator = d3.svg.arc().innerRadius(0).outerRadius(RADIUS); | |
ul.selectAll('.arc').data(pie(data)).enter().append('path').attr({ | |
"class": 'arc', | |
d: arc_generator, | |
fill: function(d, i) { | |
return color(i); | |
} | |
}); | |
radius_scale = d3.scale.linear().domain([0, max]).range([0, RADIUS]); | |
inner_radius_scale = d3.scale.linear().domain([0, max]).range([RADIUS * 0.4, RADIUS]); | |
arc_generator = d3.svg.arc().innerRadius(function(d) { | |
return inner_radius_scale(max - d.value); | |
}).outerRadius(function(d) { | |
return radius_scale(max); | |
}).startAngle(function(d) { | |
return d.angle - polar_layout.angle() / 2; | |
}).endAngle(function(d) { | |
return d.angle + polar_layout.angle() / 2; | |
}); | |
pies = um.selectAll('.arc').data(polar_data); | |
pies.enter().append('path').attr({ | |
"class": 'arc', | |
d: arc_generator, | |
fill: function(count, klass) { | |
return color(klass); | |
} | |
}); | |
max_dist = RADIUS / (1 + Math.sin(polar_layout.angle() / 2)); | |
dist_scale = d3.scale.sqrt().domain([0, max]).range([0, max_dist]); | |
bm.selectAll('.bubble').data(polar_data).enter().append('circle').attr({ | |
"class": 'bubble', | |
cx: function(d) { | |
return dist_scale(d.value) * Math.cos(d.angle - Math.PI / 2); | |
}, | |
cy: function(d) { | |
return dist_scale(d.value) * Math.sin(d.angle - Math.PI / 2); | |
}, | |
r: function(d) { | |
return dist_scale(d.value) * Math.sin(polar_layout.angle() / 2); | |
}, | |
fill: function(d, i) { | |
return color(i); | |
} | |
}); | |
radius_scale = d3.scale.sqrt().domain([0, max]).range([0, RADIUS]); | |
arc_generator = d3.svg.arc().innerRadius(0).outerRadius(function(d) { | |
return radius_scale(d.value); | |
}).startAngle(function(d) { | |
return d.angle - polar_layout.angle() / 2; | |
}).endAngle(function(d) { | |
return d.angle + polar_layout.angle() / 2; | |
}); | |
bl.selectAll('.arc').data(polar_data).enter().append('path').attr({ | |
"class": 'arc', | |
d: arc_generator, | |
fill: function(d, i) { | |
return color(i); | |
} | |
}); | |
max_dist = RADIUS / (1 + Math.sin(polar_layout.angle() / 2)); | |
dist_scale = d3.scale.sqrt().domain([0, max]).range([0, max_dist]); | |
br.selectAll('.petal').data(polar_data).enter().append('path').attr({ | |
"class": 'petal', | |
d: function(d) { | |
var far_x, far_y, l, r, theta, theta_a, theta_b; | |
r = dist_scale(d.value) * Math.sin(polar_layout.angle() / 2); | |
l = dist_scale(d.value) * Math.cos(polar_layout.angle() / 2); | |
theta = d.angle - Math.PI / 2; | |
if (l === 0) { | |
far_x = (dist_scale(d.value) + r) * Math.cos(theta); | |
far_y = (dist_scale(d.value) + r) * Math.sin(theta); | |
return "M0 0 A" + r + " " + r + " 0 1 1 " + far_x + " " + far_y + " A" + r + " " + r + " 0 1 1 0 0"; | |
} | |
theta_a = theta - polar_layout.angle() / 2; | |
theta_b = theta + polar_layout.angle() / 2; | |
return "M0 0 L" + (l * Math.cos(theta_a)) + " " + (l * Math.sin(theta_a)) + " A" + r + " " + r + " 0 1 1 " + (l * Math.cos(theta_b)) + " " + (l * Math.sin(theta_b)) + " z"; | |
}, | |
fill: function(d, i) { | |
return color(i); | |
} | |
}); | |
W = 8; | |
dist_scale = d3.scale.linear().domain([0, max]).range([0, RADIUS]); | |
ur.selectAll('.stick').data(polar_data).enter().append('path').attr({ | |
"class": 'stick', | |
d: function(d) { | |
var b_x, b_y, c_x, c_y, d_x, d_y, delta, e_x, e_y, fx, fy, nx, ny, theta; | |
theta = d.angle; | |
delta = W / 2 / Math.tan(polar_layout.angle() / 2); | |
nx = delta * Math.sin(theta); | |
ny = -delta * Math.cos(theta); | |
b_x = nx - W / 2 * Math.cos(theta); | |
b_y = ny - W / 2 * Math.sin(theta); | |
e_x = nx + W / 2 * Math.cos(theta); | |
e_y = ny + W / 2 * Math.sin(theta); | |
fx = dist_scale(d.value) * Math.sin(theta); | |
fy = -dist_scale(d.value) * Math.cos(theta); | |
c_x = fx - W / 2 * Math.cos(theta); | |
c_y = fy - W / 2 * Math.sin(theta); | |
d_x = fx + W / 2 * Math.cos(theta); | |
d_y = fy + W / 2 * Math.sin(theta); | |
return "M0 0 L" + b_x + " " + b_y + " L" + c_x + " " + c_y + " L" + d_x + " " + d_y + " L" + e_x + " " + e_y + " z"; | |
}, | |
fill: function(d, i) { | |
return color(i); | |
} | |
}); | |
}).call(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment