This post will demonstrate how to draw polygons on Google Maps v3 using geojson-encoded data from GeoDjango. The most common method for displaying polygons on Google Maps seems to be by using KML. Google Maps requires the KML-file to be available on a public website though and that is kind of a bore for debugging. This approach uses only json and the standard maps drawing API. To get the display the polygons, you have to loop over them and do a setMap() with your map.
I’m assuming the browser is getting geojson from from a GeoDjango model object like this: model.area.geojson, but it should work for data from other sources. Note that I’m using the very excellent Underscore.js Javascript library to do really terse functional programming. Also note that the function takes an optional bounds object which gets expanded as polygon points are added.
The code seems to perform very well in modern browsers, even for fairly large and complex polygons. Unfortunately there is no live demo, but the site I’m working on should go up soon.
function createPolygons(areajson, bounds){
var coords = areajson.coordinates;
var polygons = _(coords).reduce([], function(memo_n, n) {
var polygonpaths = _(n).reduce(new google.maps.MVCArray(), function(memo_o, o) {
var polygoncords = _(o).reduce(new google.maps.MVCArray(), function(memo_p, p) {
var mylatlng = new google.maps.LatLng(p[1], p[0]);
if(bounds){
bounds.extend(mylatlng);
}
memo_p.push(mylatlng);
return memo_p;
});
memo_o.push(polygoncords);
return memo_o;
});
var polygon = new google.maps.Polygon({
paths: polygonpaths,
strokeColor: "#808080",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#C0C0C0",
fillOpacity: 0.35
});
memo_n.push(polygon);
return memo_n;
});
return polygons;
}
I really like the way Javascript is moving from being this annoying thing you have to deal with when doing web-development to becoming a proper server-side programming languages with standard libraries and fast VMs. Yesterday I cloned the Narwhalgit repo and tried to create my own package with a few simple collection types. Narwhal is done by the guys at 280north and conforms to the CommonJS standard, an attempt at a cross-platform standard by the various Javascript platform implementors.
I haven’t quite figured out what goes into creating a proper package, but if you check out and configure Narwhal, you can dump the collection implementation in /lib and the tests in /tests and see it all work. First the collections:
// -- friism Michael Friis
exports.Stack = function() {
return new stack();
};
exports.Queue = function() {
return new queue();
};
/**
* Stack implementation, using native Javascript array
*/
function stack() {
this.data = [];
};
stack.prototype.pop = function() {
return this.data.pop();
};
stack.prototype.push = function(o) {
this.data.push(o);
};
/**
* Queue implementation. Mechanics lifted from Wikipedia
* Could be optimised to do fewer slices, see here:
* http://safalra.com/web-design/javascript/queues/Queue.js
*/
function queue() {
this.data = [];
this.length = 0;
}
queue.prototype.isEmpty = function() {
return (this.data.length == 0);
};
queue.prototype.enqueue = function(obj) {
this.data.push(obj);
this.length = this.data.length;
}
queue.prototype.dequeue = function() {
var ret = this.data[0];
this.data.splice(0,1);
this.length = this.data.length;
return ret;
}
queue.prototype.peek = function() {
return this.data[0];
}
queue.prototype.clear = function() {
this.length = 0;
this.data = [];
}
… and the tests:
var assert = require("test/assert");
var js5 = require("js5");
exports.testStackSimple = function() {
var mystack = new js5.Stack();
var myobject = "1";
mystack.push(myobject);
var popped = mystack.pop();
assert.isEqual(myobject, popped);
};
exports.testStack = function() {
var mystack = new js5.Stack();
for(var i = 99; i >= 0; i--) {
mystack.push(i.toString());
}
for(var j = 0; j < 100; j++) {
assert.isEqual(mystack.pop(), j.toString());
}
}
exports.testQueue = function() {
var myqueue = new js5.Queue();
for(var i = 0; i < 100; i++) {
myqueue.enqueue(i.toString());
}
for(var j = 0; j < 100; j++) {
assert.isEqual(myqueue.dequeue(), j.toString());
}
}
if (module == require.main) {
require("os").exit(require("test").run(exports));
}
I asked for help on the Narwhal IRC channel and Kris Kowal pointed me to Chiron, a module library he's working on that already contains set and dictionary implementations. I recommend checking out the code, it highligts some of the interesting challenges of implementing collections in Javascript.
Also, this "Javascript, the Good Parts" talk by Doug Crockford (author of book of the same name) is really good:
The whole Folkets Ting business has turned out rather well (even though the site is not currently updated — we’re working on it!) and I’ve been invited to speak on a few occations. Some of the talks were recorded, and in the interest of self-agrandissement they are included below in chronological order (except for the last one).
Short blurb (in Danish) on what I think about the usefulness of public data at the ODIS conference:
Speech on “Political Data API” after a project of mine won a competition promoting reuse of public data (winners were announced at the conference mentioned above):