|
<!DOCTYPE html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<title>State Grid of Dogs</title> |
|
<meta content="Essai on using tessellation in vizualisation" name="description"> |
|
<style> |
|
|
|
.state path { |
|
fill: #dedede; |
|
stroke-width: 2; |
|
stroke: white; |
|
} |
|
|
|
.state circle { |
|
fill: grey; |
|
} |
|
|
|
.state text { |
|
font: 12px sans-serif; |
|
text-anchor: middle; |
|
} |
|
|
|
.state--selected path { |
|
fill: #9f4a6c; |
|
} |
|
|
|
.state--selected circle { |
|
fill: #dedede; |
|
} |
|
|
|
.state--selected text { |
|
fill: white; |
|
} |
|
|
|
</style> |
|
</head> |
|
<body> |
|
<svg width="960" height="500"></svg> |
|
<script id="grid" type="text/plain"> |
|
AK ME |
|
WI VT NH |
|
WA ID MT ND MN IL MI NY MA |
|
OR NV WY SD IA IN OH PA NJ CT RI |
|
CA UT CO NE MO KY WV VA MD DE |
|
AZ NM KS AR TN NC SC |
|
OK LA MS AL GA |
|
HI TX FL |
|
</script> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<script> |
|
|
|
var states = [], |
|
selectedStates = ["MA", "MD", "ME", "MI", "MN", "MO", "MS", "MT", "FL"]; |
|
|
|
d3.select("#grid").text().split("\n").forEach(function(line, i) { |
|
var re = /\w+/g, m; |
|
while (m = re.exec(line)) states.push({ |
|
name: m[0], |
|
selected: selectedStates.indexOf(m[0]) >= 0, |
|
x: m.index / 3, |
|
y: i |
|
}); |
|
}); |
|
|
|
var svg = d3.select("svg"), |
|
width = +svg.attr("width"), |
|
height = +svg.attr("height"); |
|
|
|
var gridWidth = d3.max(states, function(d) { return d.x; }) + 1, |
|
gridHeight = d3.max(states, function(d) { return d.y; }) + 1, |
|
cellSize = 40, |
|
hcz = cellSize/2, //halfCellSize |
|
qcz = cellSize/4; //quarterCellSize |
|
|
|
var hVerteces = [ |
|
[-2*qcz, -2*qcz], [-qcz, -3*qcz], [qcz, -3*qcz], [qcz, -2*qcz], [2*qcz, -2*qcz] |
|
]; |
|
var vVerteces = [ |
|
[-2*qcz, -2*qcz], [-qcz, 0], [-2*qcz, 0], [-3*qcz, -qcz/2], [-2*qcz, 2*qcz] |
|
]; |
|
var shapeVerteces = |
|
hVerteces.concat( |
|
vVerteces.map(function(v){return [v[0]+cellSize, v[1]];}).concat( |
|
hVerteces.slice().reverse().map(function(v){return [v[0], v[1]+cellSize];}).concat( |
|
vVerteces.slice().reverse() |
|
) |
|
) |
|
) |
|
var shape = d3.line().curve(d3.curveBasis)(shapeVerteces); |
|
|
|
var state = svg.append("g") |
|
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")") |
|
.selectAll(".state") |
|
.data(states) |
|
.enter().append("g") |
|
.attr("class", function(d) { return "state" + (d.selected ? " state--selected" : ""); }) |
|
.attr("transform", function(d) { return "translate(" + (d.x - gridWidth / 2) * cellSize + "," + (d.y - gridHeight / 2) * cellSize + ")"; }); |
|
|
|
state.append("path") |
|
.attr("d", shape); |
|
|
|
state.append("circle") |
|
.attr("cx", 3/4*qcz) |
|
.attr("cy", -2*qcz) |
|
.attr("r", 2); |
|
|
|
state.append("text") |
|
.attr("dy", ".35em") |
|
.text(function(d) { return d.name; }); |
|
|
|
</script> |
|
</body> |