Skip to content

Instantly share code, notes, and snippets.

@tlfrd
Last active August 15, 2017 10:46
Show Gist options
  • Save tlfrd/d940d2845d43add71f331b94be98fa44 to your computer and use it in GitHub Desktop.
Save tlfrd/d940d2845d43add71f331b94be98fa44 to your computer and use it in GitHub Desktop.
London Grid with Geo Shapes
license: mit
height: 500

A grid of London constituencies with the geographical representation of each constituency resized to fit within the same rectangular area. Hover over areas for the constituency name.

forked from tlfrd's block: London Constituency Grid Layout

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="london-grid.js"></script>
<style>
body {
margin: 0;
}
.constituency {
fill: white;
stroke: black;
}
.hover-rect {
opacity: 0;
}
div.tooltip {
position: absolute;
text-align: center;
padding: 5px;
font: 12px monospace;
background-color: cyan;
border: 1px black solid;
pointer-events: none;
width: 80px;
}
</style>
</head>
<body>
<script>
var cfg = {
gridLength: 11,
gridHeight: 10,
padding: 6
}
var margin = {top: 50, right: 200, bottom: 50, left: 200};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var rectWidth = (width / cfg.gridLength) - cfg.padding,
rectHeight = (height / cfg.gridHeight) - cfg.padding;
var url = "topo_wpc_london.json";
function calculateCoords(d) {
var x = d.x * (rectWidth + cfg.padding);
var y = d.y * (rectHeight + cfg.padding);
return [x, y];
}
var londonGridLookup = {};
londonGrid.forEach(function(d) {
londonGridLookup[d.ons_code] = d;
});
var constituencies = svg.append("g").attr("class", "constituencies");
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
d3.json(url, function(topoLondon) {
var geoLondon = topojson.feature(topoLondon, topoLondon.objects.wpc).features;
constituencies.selectAll(".constituency")
.data(geoLondon)
.enter().append("path")
.attr("class", "constituency")
.attr("d", d => localProjection(d, londonGridLookup[d.id].position))
constituencies.selectAll("rect")
.data(geoLondon)
.enter().append("rect")
.attr("class", "hover-rect")
.attr("x", d => calculateCoords(londonGridLookup[d.id].position)[0])
.attr("y", d => calculateCoords(londonGridLookup[d.id].position)[1])
.attr("width", rectWidth)
.attr("height", rectHeight)
.on("mouseover", showLabel)
.on("mouseout", hideLabel);
});
function localProjection(geometry, position) {
var centroid = d3.geoPath().centroid(geometry);
var topLeftCorner = calculateCoords(position),
topRightCorner = [calculateCoords(position)[0] + rectWidth, calculateCoords(position)[1] + rectHeight];
var projection = d3.geoAlbers()
.center(centroid)
.rotate([0, 0])
.fitExtent([topLeftCorner, topRightCorner], geometry);
var path = d3.geoPath()
.projection(projection);
return path(geometry);
}
function showLabel(d) {
var left = calculateCoords(londonGridLookup[d.id].position)[0] - rectWidth / 2,
right = calculateCoords(londonGridLookup[d.id].position)[1] - rectHeight ;
div.transition()
.duration(200)
.style("opacity", 0.8)
div.html(d.properties.PCON13NM)
.style("left", (left + margin.left) + "px")
.style("top", (right + margin.top) + "px")
}
function hideLabel() {
div.transition()
.duration(200)
.style("opacity", 0);
}
</script>
</body>
var londonGrid = [
{
"ons_code": "E14000692",
"name": "Enfield Southgate",
"position": {
"x": 5,
"y": 0
}
},
{
"ons_code": "E14000691",
"name": "Enfield North",
"position": {
"x": 6,
"y": 0
}
},
{
"ons_code": "E14000731",
"name": "Harrow East",
"position": {
"x": 2,
"y": 1
}
},
{
"ons_code": "E14000741",
"name": "Hendon",
"position": {
"x": 3,
"y": 1
}
},
{
"ons_code": "E14000636",
"name": "Chipping Barnet",
"position": {
"x": 4,
"y": 1
}
},
{
"ons_code": "E14000752",
"name": "Hornsey & Wood Green",
"position": {
"x": 5,
"y": 1
}
},
{
"ons_code": "E14000687",
"name": "Edmonton",
"position": {
"x": 6,
"y": 1
}
},
{
"ons_code": "E14000634",
"name": "Chingford & Woodford Green",
"position": {
"x": 7,
"y": 1
}
},
{
"ons_code": "E14000906",
"name": "Ruislip, Northwood & Pinner",
"position": {
"x": 0,
"y": 2
}
},
{
"ons_code": "E14000732",
"name": "Harrow West",
"position": {
"x": 1,
"y": 2
}
},
{
"ons_code": "E14000592",
"name": "Brent North",
"position": {
"x": 2,
"y": 2
}
},
{
"ons_code": "E14000727",
"name": "Hampstead & Kilburn",
"position": {
"x": 3,
"y": 2
}
},
{
"ons_code": "E14000703",
"name": "Finchley & Golders Green",
"position": {
"x": 4,
"y": 2
}
},
{
"ons_code": "E14000763",
"name": "Islington North",
"position": {
"x": 5,
"y": 2
}
},
{
"ons_code": "E14001002",
"name": "Tottenham",
"position": {
"x": 6,
"y": 2
}
},
{
"ons_code": "E14001013",
"name": "Walthamstow",
"position": {
"x": 7,
"y": 2
}
},
{
"ons_code": "E14000759",
"name": "Ilford North",
"position": {
"x": 8,
"y": 2
}
},
{
"ons_code": "E14000900",
"name": "Romford",
"position": {
"x": 9,
"y": 2
}
},
{
"ons_code": "E14000751",
"name": "Hornchurch & Upminster",
"position": {
"x": 10,
"y": 2
}
},
{
"ons_code": "E14001007",
"name": "Uxbridge & Ruislip South",
"position": {
"x": 0,
"y": 3
}
},
{
"ons_code": "E14000675",
"name": "Ealing North",
"position": {
"x": 1,
"y": 3
}
},
{
"ons_code": "E14000591",
"name": "Brent Central",
"position": {
"x": 2,
"y": 3
}
},
{
"ons_code": "E14000768",
"name": "Kensington",
"position": {
"x": 3,
"y": 3
}
},
{
"ons_code": "E14000750",
"name": "Holborn & St Pancras",
"position": {
"x": 4,
"y": 3
}
},
{
"ons_code": "E14000764",
"name": "Islington South & Finsbury",
"position": {
"x": 5,
"y": 3
}
},
{
"ons_code": "E14000720",
"name": "Hackney North & Stoke Newington",
"position": {
"x": 6,
"y": 3
}
},
{
"ons_code": "E14001032",
"name": "West Ham",
"position": {
"x": 7,
"y": 3
}
},
{
"ons_code": "E14000790",
"name": "Leyton & Wanstead",
"position": {
"x": 8,
"y": 3
}
},
{
"ons_code": "E14000760",
"name": "Ilford South",
"position": {
"x": 9,
"y": 3
}
},
{
"ons_code": "E14000657",
"name": "Dagenham & Rainham",
"position": {
"x": 10,
"y": 3
}
},
{
"ons_code": "E14000737",
"name": "Hayes & Harlington",
"position": {
"x": 0,
"y": 4
}
},
{
"ons_code": "E14000676",
"name": "Ealing Southall",
"position": {
"x": 1,
"y": 4
}
},
{
"ons_code": "E14000674",
"name": "Ealing Central & Acton",
"position": {
"x": 2,
"y": 4
}
},
{
"ons_code": "E14000629",
"name": "Chelsea & Fulham",
"position": {
"x": 3,
"y": 4
}
},
{
"ons_code": "E14001036",
"name": "Westminster North",
"position": {
"x": 4,
"y": 4
}
},
{
"ons_code": "E14000553",
"name": "Bermondsey & Old Southwark",
"position": {
"x": 5,
"y": 4
}
},
{
"ons_code": "E14000721",
"name": "Hackney South & Shoreditch",
"position": {
"x": 6,
"y": 4
}
},
{
"ons_code": "E14000882",
"name": "Poplar & Limehouse",
"position": {
"x": 7,
"y": 4
}
},
{
"ons_code": "E14000679",
"name": "East Ham",
"position": {
"x": 8,
"y": 4
}
},
{
"ons_code": "E14000540",
"name": "Barking",
"position": {
"x": 9,
"y": 4
}
},
{
"ons_code": "E14000701",
"name": "Feltham & Heston",
"position": {
"x": 0,
"y": 5
}
},
{
"ons_code": "E14000593",
"name": "Brentford & Isleworth",
"position": {
"x": 1,
"y": 5
}
},
{
"ons_code": "E14000726",
"name": "Hammersmith",
"position": {
"x": 2,
"y": 5
}
},
{
"ons_code": "E14000887",
"name": "Putney",
"position": {
"x": 3,
"y": 5
}
},
{
"ons_code": "E14000639",
"name": "Cities of London & Westminster",
"position": {
"x": 4,
"y": 5
}
},
{
"ons_code": "E14001008",
"name": "Vauxhall",
"position": {
"x": 5,
"y": 5
}
},
{
"ons_code": "E14000555",
"name": "Bethnal Green & Bow",
"position": {
"x": 6,
"y": 5
}
},
{
"ons_code": "E14000718",
"name": "Greenwich & Woolwich",
"position": {
"x": 7,
"y": 5
}
},
{
"ons_code": "E14000696",
"name": "Erith & Thamesmead",
"position": {
"x": 8,
"y": 5
}
},
{
"ons_code": "E14000558",
"name": "Bexleyheath & Crayford",
"position": {
"x": 9,
"y": 5
}
},
{
"ons_code": "E14001005",
"name": "Twickenham",
"position": {
"x": 1,
"y": 6
}
},
{
"ons_code": "E14000896",
"name": "Richmond Park",
"position": {
"x": 2,
"y": 6
}
},
{
"ons_code": "E14000998",
"name": "Tooting",
"position": {
"x": 3,
"y": 6
}
},
{
"ons_code": "E14000549",
"name": "Battersea",
"position": {
"x": 4,
"y": 6
}
},
{
"ons_code": "E14000673",
"name": "Dulwich & West Norwood",
"position": {
"x": 5,
"y": 6
}
},
{
"ons_code": "E14000615",
"name": "Camberwell & Peckham",
"position": {
"x": 6,
"y": 6
}
},
{
"ons_code": "E14000789",
"name": "Lewisham Deptford",
"position": {
"x": 7,
"y": 6
}
},
{
"ons_code": "E14000690",
"name": "Eltham",
"position": {
"x": 8,
"y": 6
}
},
{
"ons_code": "E14000869",
"name": "Old Bexley & Sidcup",
"position": {
"x": 9,
"y": 6
}
},
{
"ons_code": "E14000770",
"name": "Kingston & Surbiton",
"position": {
"x": 1,
"y": 7
}
},
{
"ons_code": "E14001040",
"name": "Wimbledon",
"position": {
"x": 2,
"y": 7
}
},
{
"ons_code": "E14000823",
"name": "Mitcham & Morden",
"position": {
"x": 3,
"y": 7
}
},
{
"ons_code": "E14000978",
"name": "Streatham",
"position": {
"x": 4,
"y": 7
}
},
{
"ons_code": "E14000788",
"name": "Lewisham West & Penge",
"position": {
"x": 5,
"y": 7
}
},
{
"ons_code": "E14000787",
"name": "Lewisham East",
"position": {
"x": 6,
"y": 7
}
},
{
"ons_code": "E14000604",
"name": "Bromley & Chislehurst",
"position": {
"x": 7,
"y": 7
}
},
{
"ons_code": "E14000984",
"name": "Sutton & Cheam",
"position": {
"x": 2,
"y": 8
}
},
{
"ons_code": "E14000621",
"name": "Carshalton & Wallington",
"position": {
"x": 3,
"y": 8
}
},
{
"ons_code": "E14000655",
"name": "Croydon North",
"position": {
"x": 4,
"y": 8
}
},
{
"ons_code": "E14000654",
"name": "Croydon Central",
"position": {
"x": 5,
"y": 8
}
},
{
"ons_code": "E14000551",
"name": "Beckenham",
"position": {
"x": 6,
"y": 8
}
},
{
"ons_code": "E14000872",
"name": "Orpington",
"position": {
"x": 7,
"y": 8
}
},
{
"ons_code": "E14000656",
"name": "Croydon South",
"position": {
"x": 4,
"y": 9
}
}
]
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment