Skip to content

Instantly share code, notes, and snippets.

@nitaku
Last active August 29, 2015 14:01
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save nitaku/5c39929f53ab6af7b16f to your computer and use it in GitHub Desktop.
Hexbin polar area chart
svg = d3.select('svg')
width = svg[0][0].getBoundingClientRect().width / 2
height = svg[0][0].getBoundingClientRect().height
### left and right side of the vis ###
left = svg.append('g')
.attr('clip-path', 'url(#left)')
right = svg.append('g')
.attr('clip-path', 'url(#right)')
.append('g')
.attr('transform', 'translate(480,0)')
svg.append('line')
.attr('class', 'separator')
.attr('x1', 479.5)
.attr('y1', 0)
.attr('x2', 479.5)
.attr('y2', 500)
### random data ###
skew = 80 * Math.random()
randomX_a = d3.random.normal(width / 2 - skew, 80)
randomY_a = d3.random.normal(height / 2 - skew, 80)
points_a = d3.range(1500+1000*Math.random()).map(() -> [randomX_a(), randomY_a()])
randomX_b = d3.random.normal(width / 2 + skew, 80+80*Math.random())
randomY_b = d3.random.normal(height / 2 + skew, 80)
points_b = d3.range(2000).map(() -> [randomX_b(), randomY_b()])
randomX_c = d3.random.normal(width / 2 + skew, 120)
randomY_c = d3.random.normal(height / 2 - skew, 120)
points_c = d3.range(1500).map(() -> [randomX_c(), randomY_c()])
### dot plot ###
left.selectAll('.point.a')
.data(points_a)
.enter().append('circle')
.attr('class', 'point a')
.attr('cx', (d) -> d[0])
.attr('cy', (d) -> d[1])
.attr('r', 1)
left.selectAll('.point.b')
.data(points_b)
.enter().append('circle')
.attr('class', 'point b')
.attr('cx', (d) -> d[0])
.attr('cy', (d) -> d[1])
.attr('r', 1)
left.selectAll('.point.c')
.data(points_c)
.enter().append('circle')
.attr('class', 'point c')
.attr('cx', (d) -> d[0])
.attr('cy', (d) -> d[1])
.attr('r', 1)
### hexbin and scales ###
hexbin = d3.hexbin()
.size([width, height])
.radius(20)
radius = d3.scale.sqrt() # WARNING: Area encoding
.domain([0, 70])
.range([0, 20])
color = d3.scale.linear()
.domain([0, 20])
.range(['white', 'steelblue'])
.interpolate(d3.interpolateLab)
slice = d3.svg.arc()
.innerRadius(0)
### polar area charts - WARNING: Area encoding ###
right.selectAll('.pie.a')
.data(hexbin(points_a))
.enter().append('path')
.attr('class', 'pie a')
.attr('d', (d) ->
slice( {
outerRadius: radius(d.length)*Math.sqrt(3)/2,
startAngle: 4*Math.PI/3,
endAngle: 2*Math.PI
})
)
.attr('transform', (d) -> "translate(#{d.x},#{d.y})")
right.selectAll('.pie.b')
.data(hexbin(points_b))
.enter().append('path')
.attr('class', 'pie b')
.attr('d', (d) ->
slice( {
outerRadius: radius(d.length)*Math.sqrt(3)/2,
startAngle: 0,
endAngle: 2*Math.PI/3
})
)
.attr('transform', (d) -> "translate(#{d.x},#{d.y})")
right.selectAll('.pie.c')
.data(hexbin(points_c))
.enter().append('path')
.attr('class', 'pie c')
.attr('d', (d) ->
slice( {
outerRadius: radius(d.length)*Math.sqrt(3)/2,
startAngle: 2*Math.PI/3,
endAngle: 4*Math.PI/3
})
)
.attr('transform', (d) -> "translate(#{d.x},#{d.y})")
body {
margin: 0;
padding: 0;
}
svg {
background: white;
display: inline-block;
margin: 0;
padding: 0;
}
.separator {
stroke: #DEDEDE;
}
.a {
fill: teal;
}
.b {
fill: orange;
}
.c {
fill: purple;
}
.pie {
fill-opacity: 0.7;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="Hexbin polar area chart" />
<title>Hexbin polar area chart</title>
<link rel="stylesheet" href="index.css">
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/d3.hexbin.v0.min.js?5c6e4f0"></script>
</head>
<body>
<svg height="500" width="960">
<defs>
<clipPath id="left">
<rect x="0" y="0" width="480" height="500" />
</clipPath>
<clipPath id="right">
<rect x="480" y="0" width="480" height="500" />
</clipPath>
</defs>
</svg>
<script src="index.js"></script>
</body>
</html>
(function() {
var color, height, hexbin, left, points_a, points_b, points_c, radius, randomX_a, randomX_b, randomX_c, randomY_a, randomY_b, randomY_c, right, skew, slice, svg, width;
svg = d3.select('svg');
width = svg[0][0].getBoundingClientRect().width / 2;
height = svg[0][0].getBoundingClientRect().height;
/* left and right side of the vis
*/
left = svg.append('g').attr('clip-path', 'url(#left)');
right = svg.append('g').attr('clip-path', 'url(#right)').append('g').attr('transform', 'translate(480,0)');
svg.append('line').attr('class', 'separator').attr('x1', 479.5).attr('y1', 0).attr('x2', 479.5).attr('y2', 500);
/* random data
*/
skew = 80 * Math.random();
randomX_a = d3.random.normal(width / 2 - skew, 80);
randomY_a = d3.random.normal(height / 2 - skew, 80);
points_a = d3.range(1500 + 1000 * Math.random()).map(function() {
return [randomX_a(), randomY_a()];
});
randomX_b = d3.random.normal(width / 2 + skew, 80 + 80 * Math.random());
randomY_b = d3.random.normal(height / 2 + skew, 80);
points_b = d3.range(2000).map(function() {
return [randomX_b(), randomY_b()];
});
randomX_c = d3.random.normal(width / 2 + skew, 120);
randomY_c = d3.random.normal(height / 2 - skew, 120);
points_c = d3.range(1500).map(function() {
return [randomX_c(), randomY_c()];
});
/* dot plot
*/
left.selectAll('.point.a').data(points_a).enter().append('circle').attr('class', 'point a').attr('cx', function(d) {
return d[0];
}).attr('cy', function(d) {
return d[1];
}).attr('r', 1);
left.selectAll('.point.b').data(points_b).enter().append('circle').attr('class', 'point b').attr('cx', function(d) {
return d[0];
}).attr('cy', function(d) {
return d[1];
}).attr('r', 1);
left.selectAll('.point.c').data(points_c).enter().append('circle').attr('class', 'point c').attr('cx', function(d) {
return d[0];
}).attr('cy', function(d) {
return d[1];
}).attr('r', 1);
/* hexbin and scales
*/
hexbin = d3.hexbin().size([width, height]).radius(20);
radius = d3.scale.sqrt().domain([0, 70]).range([0, 20]);
color = d3.scale.linear().domain([0, 20]).range(['white', 'steelblue']).interpolate(d3.interpolateLab);
slice = d3.svg.arc().innerRadius(0);
/* polar area charts - WARNING: Area encoding
*/
right.selectAll('.pie.a').data(hexbin(points_a)).enter().append('path').attr('class', 'pie a').attr('d', function(d) {
return slice({
outerRadius: radius(d.length) * Math.sqrt(3) / 2,
startAngle: 4 * Math.PI / 3,
endAngle: 2 * Math.PI
});
}).attr('transform', function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
right.selectAll('.pie.b').data(hexbin(points_b)).enter().append('path').attr('class', 'pie b').attr('d', function(d) {
return slice({
outerRadius: radius(d.length) * Math.sqrt(3) / 2,
startAngle: 0,
endAngle: 2 * Math.PI / 3
});
}).attr('transform', function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
right.selectAll('.pie.c').data(hexbin(points_c)).enter().append('path').attr('class', 'pie c').attr('d', function(d) {
return slice({
outerRadius: radius(d.length) * Math.sqrt(3) / 2,
startAngle: 2 * Math.PI / 3,
endAngle: 4 * Math.PI / 3
});
}).attr('transform', function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment