Skip to content

Instantly share code, notes, and snippets.

@fod
Forked from mbostock/.block
Created July 11, 2011 19:12
Show Gist options
  • Save fod/1076558 to your computer and use it in GitHub Desktop.
Save fod/1076558 to your computer and use it in GitHub Desktop.
Fancy Markers

The default display for GeoJSON points in Polymaps is a 4.5px-radius circle. In this example, I show how to create more traditional pin-style markers for points. This is implemented using a “load” event handler which replaces the default circles with custom path elements.

The marker outline is courtesy of Dmitry Baranovskiy; he has graciously provided over 100 free vector icons to choose from. Of course, there’s no requirement to use vector icons. You could replace the circles with image elements instead, if you prefer raster. But the nice thing about vectors is that we can color them dynamically based on the data, as we do here by generating three categorical color gradients.

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://github.com/simplegeo/polymaps/raw/v2.3.0/polymaps.min.js"></script>
<script type="text/javascript" src="http://github.com/simplegeo/polymaps/raw/v2.3.0/lib/raphaeljs/icons.js"></script>
<script type="text/javascript" src="http://github.com/simplegeo/polymaps/raw/v2.3.0/lib/crimespotting/crimespotting.js"></script>
<style type="text/css">
@import url("http://github.com/simplegeo/polymaps/raw/v2.3.0/examples/example.css");
html, body {
height: 100%;
background: #E6E6E6;
}
svg {
display: block;
}
.layer use {
stroke: #ccc;
stroke-opacity: .5;
}
</style>
</head>
<body>
<script type="text/javascript">
var po = org.polymaps;
var svg = document.body.appendChild(po.svg("svg")),
defs = svg.appendChild(po.svg("defs"));
/* Create three linear gradients for each category. */
defs.appendChild(gradient("#D90000", "#A30000")).setAttribute("id", "gradient-violent");
defs.appendChild(gradient("#23965E", "#1A7046")).setAttribute("id", "gradient-property");
defs.appendChild(gradient("#3489BA", "#27678B")).setAttribute("id", "gradient-quality");
/* Create a marker path. */
defs.appendChild(icons.marker()).setAttribute("id", "marker");
var map = po.map()
.container(svg)
.center({lat: 37.787, lon: -122.228})
.zoomRange([10, 16])
.add(po.interact());
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.", ""])));
map.add(po.geoJson()
.url(crimespotting("http://oakland.crimespotting.org"
+ "/crime-data"
+ "?count=100"
+ "&format=json"
+ "&bbox={B}"
+ "&dstart=2010-04-01"
+ "&dend=2010-04-01"))
.on("load", load)
.clip(false)
.scale("fixed")
.zoom(12));
/* Post-process the GeoJSON points and replace them with markers! */
function load(e) {
e.features.sort(function(a, b) {
return b.data.geometry.coordinates[1] - a.data.geometry.coordinates[1];
});
for (var i = 0; i < e.features.length; i++) {
var f = e.features[i],
d = f.data,
c = f.element,
p = c.parentNode,
u = f.element = po.svg("use");
u.setAttributeNS(po.ns.xlink, "href", "#marker");
u.setAttribute("transform", c.getAttribute("transform"));
u.setAttribute("fill", "url(#gradient-" + crimespotting.categorize(d) + ")");
p.removeChild(c);
p.appendChild(u);
}
}
/* Helper method for constructing a linear gradient. */
function gradient(a, b) {
var g = po.svg("linearGradient");
g.setAttribute("x1", 0);
g.setAttribute("y1", 1);
g.setAttribute("x2", 0);
g.setAttribute("y2", 0);
var s0 = g.appendChild(po.svg("stop"));
s0.setAttribute("offset", "0%");
s0.setAttribute("stop-color", a);
var s1 = g.appendChild(po.svg("stop"));
s1.setAttribute("offset", "100%");
s1.setAttribute("stop-color", b);
return g;
}
</script>
<span id="copy">
&copy; 2010
<a href="http://www.cloudmade.com/">CloudMade</a>,
<a href="http://www.openstreetmap.org/">OpenStreetMap</a> contributors,
<a href="http://creativecommons.org/licenses/by-sa/2.0/">CCBYSA</a>.
</span>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment