Skip to content

Instantly share code, notes, and snippets.

@rgdonohue
Last active December 10, 2015 23:03
Show Gist options
  • Save rgdonohue/bb2fdafab5ee7532df52 to your computer and use it in GitHub Desktop.
Save rgdonohue/bb2fdafab5ee7532df52 to your computer and use it in GitHub Desktop.
Perceptual scaling of prop symbols

This example shows a solution to achieve perceptual (or apparent) scaling of graduated symbols, using the Leaflet library. Data are raw totals of Kenyan girls enrolled in the 8th grade by county.

Apparently we've never been calculating the area of our circles for graduated symbols?

var data = {
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "WOMEN": 276480, "G8": 7265 }, "geometry": { "type": "Point", "coordinates": [ 35.946, 0.669 ] } },
{ "type": "Feature", "properties": { "WOMEN": 364459, "G8": 10983 }, "geometry": { "type": "Point", "coordinates": [ 35.299, -0.726 ] } },
{ "type": "Feature", "properties": { "WOMEN": 703515, "G8": 19593 }, "geometry": { "type": "Point", "coordinates": [ 34.64, 0.749 ] } },
{ "type": "Feature", "properties": { "WOMEN": 387824, "G8": 8889 }, "geometry": { "type": "Point", "coordinates": [ 34.194, 0.387 ] } },
{ "type": "Feature", "properties": { "WOMEN": 186260, "G8": 5950 }, "geometry": { "type": "Point", "coordinates": [ 35.537, 0.802 ] } },
{ "type": "Feature", "properties": { "WOMEN": 261909, "G8": 6561 }, "geometry": { "type": "Point", "coordinates": [ 37.627, -0.604 ] } },
{ "type": "Feature", "properties": { "WOMEN": 288121, "G8": 2493 }, "geometry": { "type": "Point", "coordinates": [ 40.199, -0.489 ] } },
{ "type": "Feature", "properties": { "WOMEN": 501340, "G8": 11827 }, "geometry": { "type": "Point", "coordinates": [ 34.359, -0.543 ] } },
{ "type": "Feature", "properties": { "WOMEN": 69600, "G8": 1442 }, "geometry": { "type": "Point", "coordinates": [ 38.542, 1.01 ] } },
{ "type": "Feature", "properties": { "WOMEN": 342166, "G8": 7076 }, "geometry": { "type": "Point", "coordinates": [ 36.909, -2.121 ] } },
{ "type": "Feature", "properties": { "WOMEN": 859662, "G8": 22085 }, "geometry": { "type": "Point", "coordinates": [ 34.745, 0.404 ] } },
{ "type": "Feature", "properties": { "WOMEN": 376359, "G8": 12004 }, "geometry": { "type": "Point", "coordinates": [ 35.314, -0.296 ] } },
{ "type": "Feature", "properties": { "WOMEN": 820673, "G8": 20077 }, "geometry": { "type": "Point", "coordinates": [ 36.824, -1.069 ] } },
{ "type": "Feature", "properties": { "WOMEN": 574209, "G8": 14485 }, "geometry": { "type": "Point", "coordinates": [ 39.687, -3.176 ] } },
{ "type": "Feature", "properties": { "WOMEN": 267424, "G8": 6514 }, "geometry": { "type": "Point", "coordinates": [ 37.32, -0.525 ] } },
{ "type": "Feature", "properties": { "WOMEN": 601818, "G8": 13499 }, "geometry": { "type": "Point", "coordinates": [ 34.775, -0.775 ] } },
{ "type": "Feature", "properties": { "WOMEN": 494149, "G8": 11499 }, "geometry": { "type": "Point", "coordinates": [ 34.835, -0.169 ] } },
{ "type": "Feature", "properties": { "WOMEN": 531427, "G8": 17780 }, "geometry": { "type": "Point", "coordinates": [ 38.407, -1.491 ] } },
{ "type": "Feature", "properties": { "WOMEN": 333934, "G8": 7510 }, "geometry": { "type": "Point", "coordinates": [ 39.19, -4.183 ] } },
{ "type": "Feature", "properties": { "WOMEN": 200602, "G8": 5323 }, "geometry": { "type": "Point", "coordinates": [ 36.772, 0.324 ] } },
{ "type": "Feature", "properties": { "WOMEN": 48494, "G8": 1233 }, "geometry": { "type": "Point", "coordinates": [ 40.883, -2.079 ] } },
{ "type": "Feature", "properties": { "WOMEN": 555445, "G8": 15311 }, "geometry": { "type": "Point", "coordinates": [ 37.413, -1.28 ] } },
{ "type": "Feature", "properties": { "WOMEN": 453817, "G8": 15150 }, "geometry": { "type": "Point", "coordinates": [ 37.788, -2.158 ] } },
{ "type": "Feature", "properties": { "WOMEN": 465813, "G8": 1584 }, "geometry": { "type": "Point", "coordinates": [ 40.739, 3.436 ] } },
{ "type": "Feature", "properties": { "WOMEN": 140054, "G8": 1650 }, "geometry": { "type": "Point", "coordinates": [ 37.57, 2.979 ] } },
{ "type": "Feature", "properties": { "WOMEN": 685645, "G8": 15012 }, "geometry": { "type": "Point", "coordinates": [ 37.764, 0.167 ] } },
{ "type": "Feature", "properties": { "WOMEN": 472814, "G8": 11098 }, "geometry": { "type": "Point", "coordinates": [ 34.363, -0.99 ] } },
{ "type": "Feature", "properties": { "WOMEN": 452446, "G8": 8499 }, "geometry": { "type": "Point", "coordinates": [ 39.651, -4.021 ] } },
{ "type": "Feature", "properties": { "WOMEN": 484717, "G8": 11810 }, "geometry": { "type": "Point", "coordinates": [ 37.033, -0.81 ] } },
{ "type": "Feature", "properties": { "WOMEN": 1533139, "G8": 24960 }, "geometry": { "type": "Point", "coordinates": [ 36.868, -1.293 ] } },
{ "type": "Feature", "properties": { "WOMEN": 798743, "G8": 22675 }, "geometry": { "type": "Point", "coordinates": [ 36.078, -0.464 ] } },
{ "type": "Feature", "properties": { "WOMEN": 376477, "G8": 10633 }, "geometry": { "type": "Point", "coordinates": [ 35.11, 0.187 ] } },
{ "type": "Feature", "properties": { "WOMEN": 421894, "G8": 7312 }, "geometry": { "type": "Point", "coordinates": [ 35.576, -1.255 ] } },
{ "type": "Feature", "properties": { "WOMEN": 311204, "G8": 7262 }, "geometry": { "type": "Point", "coordinates": [ 34.965, -0.643 ] } },
{ "type": "Feature", "properties": { "WOMEN": 304113, "G8": 9486 }, "geometry": { "type": "Point", "coordinates": [ 36.483, -0.322 ] } },
{ "type": "Feature", "properties": { "WOMEN": 353833, "G8": 9550 }, "geometry": { "type": "Point", "coordinates": [ 36.956, -0.343 ] } },
{ "type": "Feature", "properties": { "WOMEN": 111940, "G8": 1385 }, "geometry": { "type": "Point", "coordinates": [ 37.118, 1.317 ] } },
{ "type": "Feature", "properties": { "WOMEN": 443652, "G8": 10828 }, "geometry": { "type": "Point", "coordinates": [ 34.248, -0.062 ] } },
{ "type": "Feature", "properties": { "WOMEN": 139323, "G8": 4205 }, "geometry": { "type": "Point", "coordinates": [ 38.419, -3.435 ] } },
{ "type": "Feature", "properties": { "WOMEN": 120222, "G8": 1838 }, "geometry": { "type": "Point", "coordinates": [ 39.418, -1.526 ] } },
{ "type": "Feature", "properties": { "WOMEN": 186879, "G8": 4681 }, "geometry": { "type": "Point", "coordinates": [ 37.87, -0.207 ] } },
{ "type": "Feature", "properties": { "WOMEN": 411585, "G8": 9909 }, "geometry": { "type": "Point", "coordinates": [ 34.957, 1.051 ] } },
{ "type": "Feature", "properties": { "WOMEN": 410330, "G8": 3175 }, "geometry": { "type": "Point", "coordinates": [ 35.436, 3.425 ] } },
{ "type": "Feature", "properties": { "WOMEN": 445185, "G8": 9968 }, "geometry": { "type": "Point", "coordinates": [ 35.322, 0.526 ] } },
{ "type": "Feature", "properties": { "WOMEN": 291906, "G8": 8032 }, "geometry": { "type": "Point", "coordinates": [ 34.722, 0.076 ] } },
{ "type": "Feature", "properties": { "WOMEN": 298175, "G8": 1505 }, "geometry": { "type": "Point", "coordinates": [ 40.035, 1.808 ] } },
{ "type": "Feature", "properties": { "WOMEN": 257863, "G8": 4503 }, "geometry": { "type": "Point", "coordinates": [ 35.244, 1.74 ] } },
{ "type": "Feature", "properties": { "WOMEN": null, "G8": null }, "geometry": null }
]
}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Perceptual Scaling</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
<style>
body { margin:0; padding:0; font-family: sans-serif; }
#map { position:absolute; top:0; bottom:0; width:960px; height: 540px; }
h1 { position: absolute; left: 50px; top: 10px; padding: 8px 2%; margin: 0; background: rgba(255,121,0,0.8); box-shadow: 0 0 15px rgba(0,0,0,0.2); border-radius: 3px; color: whitesmoke; font-weight: normal; font-size: 1.4em; }
</style>
</head>
<body>
<div id='map'></div>
<h1>Kenyan girls enrolled in 8th grade in 2014 by county</h1>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
<script src="data.js"></script>
<script>
var map = L.map('map', {
center: [-.23, 37.8],
zoom: 7
});
L.tileLayer('http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
// you need to know what the min value is,
// calculated at runtime or prior
var minValue = 1233;
// minimum desired radius size of circles
var minRadius = 8;
L.geoJson(data, {
pointToLayer: function(feature, ll){
return L.circleMarker(ll, {
color: '#ff7900',
opacity: 1,
weight: 2,
fillColor: '#ff7900',
fillOpacity: .6,
//radius: 10
radius: calcRadius(feature.properties.G8)
});
}
}).addTo(map);
function calcRadius(val) {
return 1.0083 * Math.pow(val/minValue,.5716) * minRadius;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment