Skip to content

Instantly share code, notes, and snippets.

@tcuongtran
Last active February 24, 2017 20:56
Show Gist options
  • Save tcuongtran/f92b54af05c11d111ba096302d3d3aa3 to your computer and use it in GitHub Desktop.
Save tcuongtran/f92b54af05c11d111ba096302d3d3aa3 to your computer and use it in GitHub Desktop.
D3 Hexagon State Grid Map with Legend
!function(){d3.hexbin=function(){function u(n){var r={};return n.forEach(function(n,t){var a=s.call(u,n,t)/o,e=Math.round(a),c=h.call(u,n,t)/i-(1&e?.5:0),f=Math.round(c),l=a-e;if(3*Math.abs(l)>1){var v=c-f,g=f+(f>c?-1:1)/2,m=e+(e>a?-1:1),M=c-g,d=a-m;v*v+l*l>M*M+d*d&&(f=g+(1&e?1:-1)/2,e=m)}var j=f+"-"+e,p=r[j];p?p.push(n):(p=r[j]=[n],p.i=f,p.j=e,p.x=(f+(1&e?.5:0))*i,p.y=e*o)}),d3.values(r)}function a(r){var t=0,u=0;return n.map(function(n){var a=Math.sin(n)*r,e=-Math.cos(n)*r,i=a-t,o=e-u;return t=a,u=e,[i,o]})}var e,i,o,c=1,f=1,h=r,s=t;return u.x=function(n){return arguments.length?(h=n,u):h},u.y=function(n){return arguments.length?(s=n,u):s},u.hexagon=function(n){return arguments.length<1&&(n=e),"m"+a(n).join("l")+"z"},u.centers=function(){for(var n=[],r=0,t=!1,u=0;f+e>r;r+=o,t=!t,++u)for(var a=t?i/2:0,h=0;c+i/2>a;a+=i,++h){var s=[a,r];s.i=h,s.j=u,n.push(s)}return n},u.mesh=function(){var n=a(e).slice(0,4).join("l");return u.centers().map(function(r){return"M"+r+"m"+n}).join("")},u.size=function(n){return arguments.length?(c=+n[0],f=+n[1],u):[c,f]},u.radius=function(n){return arguments.length?(e=+n,i=2*e*Math.sin(Math.PI/3),o=1.5*e,u):e},u.radius(1)};var n=d3.range(0,2*Math.PI,Math.PI/3),r=function(n){return n[0]},t=function(n){return n[1]}}();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="d3.hexbin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.21.0/d3-legend.min.js"></script>
<script>
var states = [],
radius = 25,
cellSize = radius + 20,
hexbin = d3.hexbin()
.size([width, height])
.radius(radius),
stateGrid = [
['AK', '00', '00', '00', '00', '00', '00', '00', '00', '00', 'ME'],
['00', '00', '00', '00', '00', 'WI', '00', '00', '00','VT', 'NH'],
['WA', 'ID', 'MT', 'ND', 'MN', 'IL', 'MI', '00', 'NY', 'MA'],
['OR', 'NV', 'WY', 'SD', 'IA', 'IN', 'OH', 'PA', 'NJ', 'CT', 'RI'],
['CA', 'UT', 'CO', 'NE', 'MO', 'KY', 'WV', 'VA', 'MD', 'DE'],
['00', 'AZ', 'NM', 'KS', 'AR', 'TN', 'NC', 'SC'],
['00', '00', '00', 'OK', 'LA', 'MS', 'AL', 'GA'],
['HI', '00', '00', 'TX', '00', '00', '00', 'FL']
],
svg = d3.select('svg'),
width = +svg.attr('width'),
height = +svg.attr('height'),
gridWidth,
gridHeight,
fillColor = d3.scaleThreshold()
.domain([10, 25, 50, 100, 200, 400, 1000])
.range(['#0b8fff', '#0e77d1', '#0b61ac', '#0a5698', '#09487e', '#083e6d', '#09579a']),
g,
i,
j,
legend;
for (i = 0; i < stateGrid.length; i++) {
for (j = 0; j < stateGrid[i].length; j++) {
var state = stateGrid[i][j];
if (state !== '00') {
if (i % 2 == 0) {
states.push({
name: state,
x: j,
y: i,
value: Math.floor(Math.random() * (1000 - 0) + 0)
});
} else {
states.push({
name: state,
x: j + 0.5,
y: i,
value: Math.floor(Math.random() * (1000 - 0) + 0)
});
}
}
}
}
gridWidth = d3.max(states, function(d) { return d.x; }) + 1,
gridHeight = d3.max(states, function(d) { return d.y; }) + 1;
g = svg.append('g')
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
for (i = 0; i < states.length; i++) {
var d = states[i],
horizontalPadding = 2,
verticalPadding = - 5,
xPoint = (d.x - gridWidth / 2) * (cellSize + horizontalPadding),
yPoint = hexY = (d.y - gridHeight / 2) * (cellSize + verticalPadding);
g.append('path')
.attr('class', 'hexagon')
.attr('d', hexbin.hexagon())
.attr('fill', 'white')
.attr('transform', 'translate(' + xPoint + ',' + yPoint + ')')
.transition()
.duration(500)
.delay(i * 5)
.attr('transform', 'translate(' + xPoint + ',' + yPoint + ')')
.style('fill', fillColor(d.value));
g.append('text')
.attr('fill', 'white')
.attr('text-anchor', 'middle')
.attr('alignment-baseline', 'middle')
.attr('transform', 'translate(' + xPoint + ',' + yPoint + ')')
.attr('class', 'title')
.transition()
.duration(600)
.delay(i * 10)
.attr('transform', 'translate(' + xPoint + ',' + yPoint + ')')
.text(d.name);
}
svg.append('g')
.attr('class', 'legendThreshold')
.attr('transform', 'translate(' + (width - 200) + ',20)');
legend = d3.legendColor()
.labelFormat(d3.format(',.0f'))
.labels(function({ i, genLength, generatedLabels }){
if (i === 0 ){
return generatedLabels[i]
.replace('NaN', '0')
}
return generatedLabels[i]
})
.shape('path', hexbin.hexagon(10))
.scale(fillColor);
svg.select('.legendThreshold')
.call(legend);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment