Skip to content

Instantly share code, notes, and snippets.

@gouldingken
Forked from mbostock/.block
Created March 30, 2012 16:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gouldingken/2252541 to your computer and use it in GitHub Desktop.
Save gouldingken/2252541 to your computer and use it in GitHub Desktop.
Polymaps + D3.layout.pie
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.29.5"></script>
<script type="text/javascript" src="http://polymaps.org/polymaps.min.js?2.5.0"></script>
<style type="text/css">
@import url("http://polymaps.org/style.css");
html, body {
height: 100%;
background: #E6E6E6;
margin: 0;
font: 10px sans-serif;
}
svg {
display: block;
}
.label {
font: 10px Verdana, Arial, Helvetica, sans-serif;
margin-left: 5px;
}
#map {
width: 960px;
height: 500px;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="text/javascript">
var
rm = 1,
n = 1,
color = d3.scale.category20(),
makeStar = function (d) {
var values = d.value[3];
//--setting the value of n here permits arrays of different lengths to be used, but this is not recommended as it skews the areas in the visualization as well as the positions of the wedges.
//--it is recommended to use equal length arrays and use zeros where data is not available.
n = values.length;
return star(values);
},
star = d3.layout.pie().sort(null).value(function (d) {
return 1 / n;//for a star chart, we use a constant angle rather than an angle based on the data value
}),
starRad = function (d) {
return Math.sqrt(d.data) * rm;//use the area of the wedge to represent the value. r is a radius multiplier and can be modified for different data sets.
},
arc = d3.svg.arc().innerRadius(0).outerRadius(starRad),
midAngle = function (d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
};
var po = org.polymaps;
var svg = po.svg("svg:svg");//fix for Firefox: https://github.com/simplegeo/polymaps/issues/115
svg.setAttribute('width', '100%');
svg.setAttribute('height', '100%');
// Create the map object, add it to #map…
var map = po.map()
.container(document.getElementById("map").appendChild(svg))
.zoom(8)
.add(po.interact());
// Add the CloudMade image tiles as a base layer…
map.add(po.image()
.url(po.url("http://{S}tile.cloudmade.com"
+ "/1a1b06b230af4efdbb989ea99e9841af" // http://cloudmade.com/register
+ "/998/256/{Z}/{X}/{Y}.png")
.hosts(["a.", "b.", "c.", ""])));
// Add the compass control on top.
map.add(po.compass()
.pan("none"));
// Load the station data. When the data comes back, display it.
d3.json("stations.json", function (data) {
// Insert our layer beneath the compass.
var layer = d3.select("#map svg").insert("svg:g", ".compass");
var marker = layer.selectAll("g")
.data(d3.entries(data))
.enter().append("svg:g")
.attr("transform", transform);
var arcs = marker.selectAll("g.arc")
.data(makeStar)
.enter()
.append("g")
.attr("class", "arc");
arcs.append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc);
var labels = arcs.filter(function (d) {
//--use this to filter out elements that are too small to label
return d.data > 2;
})
.append("g")
.attr("class", "label")
.attr("visibility", labelVisibility)
.attr("transform", labelTransform);
labels.append("text")
.attr("dy", ".35em")
.attr("transform", function (d) {
//--rotate text so it doesn't go upside down!
//--translate by 1px to offset from edge slightly
return (midAngle(d) > Math.PI) ? "rotate(180) translate(-1,0)" : "translate(1,0)";
})
.attr("text-anchor", function (d) {
return (midAngle(d) > Math.PI) ? "end" : "start";
})
.text(function (d, i) {
return d.data.toFixed(0);
});
// Whenever the map moves, update the marker positions.
var lastZoom = map.zoom();
map.on("move", function () {
marker.attr("transform", transform);
var zoom = map.zoom();
if (zoom != lastZoom) {//there is no on("zoomChanged") option for polymaps. For efficiency we don't want to rerun all these calculations for pan events - only when the zoom actually changes
lastZoom = zoom;
labels.attr("visibility", labelVisibility);
labels.attr("transform", labelTransform);
}
});
function getPartialScale() {
//--its has a nice effect if the pies also scale with the map, but at a different rate
//--play with the power for different effects
var p = 3;
return Math.pow(0.1, (p - 1)) * Math.pow(map.zoom(), p);
}
function labelTransform(d) {
if (!labelsVisible()) return "";//--no need to trigger matrix calculations if these aren't even visible
return "rotate(" + (midAngle(d) * 180 / Math.PI - 90) + ") "
+ "translate(" + starRad(d) + ",0) "
+ "scale(" + 1 / getPartialScale() + ") ";//invert the parent element scale to use actual font size
}
function labelVisibility() {
return (labelsVisible()) ? "visible " : "hidden";
}
function labelsVisible() {//--only show the labels when we're fully zoomed in...
return map.zoom() > 11;
}
function transform(d) {
d = map.locationPoint({lon:d.value[0], lat:d.value[1]});
return "translate(" + d.x + "," + d.y + ") scale(" + getPartialScale() + ")";
}
});
</script>
</body>
</html>
{"KMAE":[-120.12,36.98,"MADERA MUNICIPAL AIRPORT",[26,1,2,5,6,3,2,1,2,7,29,12,3]],"KSJC":[-121.92,37.37,"SAN JOSE INTERNATIONAL AIRPORT",[28,1,1,1,6,10,5,3,2,4,14,21,7]],"KMCE":[-120.50,37.28,"MERCED MUNICIPAL AIRPORT",[29,1,1,3,7,5,2,1,3,6,12,26,5]],"KMER":[-120.57,37.37,"Merced / Castle Air Force Base",[34,1,1,1,4,5,2,1,1,4,17,22,7]],"KAPC":[-122.28,38.20,"NAPA COUNTY AIRPORT",[23,2,1,6,3,3,8,18,11,13,4,3,5]],"KSUU":[-121.95,38.27,"Fairfield / Travis Air Force Base",[13,7,4,3,3,6,4,13,33,4,1,2,7]],"KSQL":[-122.25,37.52,"San Carlos Airport",[18,3,2,2,3,4,3,2,5,17,16,12,12]],"KSNS":[-121.60,36.67,"SALINAS MUNICIPAL AIRPORT",[21,1,1,6,12,3,1,2,9,21,17,5,1]],"KMOD":[-120.95,37.62,"MODESTO CITY CO SHAM FLD",[27,1,1,2,10,5,1,1,1,3,17,24,8]],"KOAK":[-122.23,37.72,"METRO OAKLAND INTERNATIONAL AIRPORT ",[16,3,3,2,4,6,3,4,9,23,20,6,2]],"KSCK":[-121.23,37.90,"STOCKTON METROPOLITAN AIRPORT ",[21,2,2,3,6,8,2,1,4,15,19,12,4]],"KCCR":[-122.05,38.00,"CONCORD BUCHANAN FIELD",[24,3,2,1,1,5,17,12,9,9,7,6,4]],"KMRY":[-121.85,36.58,"MONTEREY PENINSULA AIRPORT",[26,1,2,9,5,3,4,9,13,14,9,4,1]],"KPAO":[-122.12,37.47,"Palo Alto Airport",[31,3,1,1,2,5,1,1,1,4,10,25,14]],"KSAC":[-121.50,38.50,"SACRAMENTO EXECUTIVE AIRPORT ",[32,1,0,1,3,11,12,16,5,2,4,9,3]],"KHWD":[-122.12,37.67,"HAYWARD AIR TERMINAL",[20,2,7,2,2,6,3,3,6,23,18,6,2]],"KSTS":[-122.82,38.50,"SANTA ROSA SONOMA COUNTY",[46,1,0,1,5,13,10,4,3,3,4,6,3]],"KSMF":[-121.60,38.70,"SACRAMENTO INTERNATIONAL AIRPORT",[19,2,1,2,4,21,18,8,3,2,5,12,4]],"KNUQ":[-122.05,37.43,"MOFFETT FIELD",[35,3,1,1,4,7,2,1,2,5,6,17,15]],"KRHV":[-121.82,37.33,"San Jose / Reid / Hillv",[35,0,0,1,4,4,2,1,1,10,28,11,1]],"KWVI":[-121.78,36.93,"WATSONVILLE MUNICIPAL AIRPORT ",[44,1,2,3,4,5,7,9,8,4,6,5,2]],"KMHR":[-121.30,38.55,"Sacramento, Sacramento Mather Airport",[21,1,1,2,8,15,12,12,7,4,5,7,3]],"KVCB":[-121.95,38.38,"VACAVILLE NUT TREE AIRPORT",[36,2,1,1,2,6,10,18,10,2,2,5,6]],"KSFO":[-122.37,37.62,"SAN FRANCISCO INTERNATIONAL AIRPORT ",[13,3,3,2,3,4,4,4,7,31,20,2,3]],"KLVK":[-121.82,37.70,"LIVERMORE MUNICIPAL AIRPORT ",[32,2,7,3,1,1,2,7,9,17,16,2,1]]}
@gouldingken
Copy link
Author

This fork adds a star chart for each station using d3.layout.pie

@gouldingken
Copy link
Author

The latest revision adds labels when zoomed in past a threshold.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment