(function() { window.main = function() { /* "globals" */ var container, dx, dy, height, path_generator, radius, svg, vis, width; vis = null; width = 960; height = 500; svg = d3.select('body').append('svg').attr('width', width).attr('height', height); /* ZOOM and PAN */ /* create container elements */ container = svg.append('g').attr('transform', 'translate(640, 34)'); container.call(d3.behavior.zoom().scaleExtent([1, 49]).on('zoom', (function() { return vis.attr('transform', "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); }))); vis = container.append('g'); /* create a rectangular overlay to catch events */ /* WARNING rect size is huge but not infinite. this is a dirty hack */ vis.append('rect').attr('class', 'overlay').attr('x', -500000).attr('y', -500000).attr('width', 1000000).attr('height', 1000000); /* END ZOOM and PAN */ /* custom projection to make hexagons appear regular (y axis is also flipped) */ radius = 1; dx = radius * 2 * Math.sin(Math.PI / 3); dy = radius * 1.5; path_generator = d3.geo.path().projection(d3.geo.transform({ point: function(x, y, z) { /* draw only nodes that are "important" enough */ return this.stream.point(x * dx / 2, -(y - (2 - (y & 1)) / 3) * dy / 2); } })); /* load topoJSON data */ return d3.json('regions_48207.topo.json', function(error, data) { /* presimplify the topology (compute the effective area (z) of each point) */ /* data.objects contain all the map layers */ /* each layer represents a different level of the tree */ /* the number of layers is equal to the depth of the tree */ var defs, depth, i; depth = Object.keys(data.objects).length; /* draw the level zero region (the land) */ defs = svg.append('defs'); defs.selectAll('#land').data(topojson.feature(data, data.objects[0]).features).enter().append('path').attr('id', 'land').attr('d', path_generator); /* faux land glow (using filters takes too much resources) */ vis.append('use').attr('class', 'land-glow-outer').attr('xlink:href', '#land'); vis.append('use').attr('class', 'land-glow-inner').attr('xlink:href', '#land'); vis.append('use').attr('class', 'land-fill').attr('xlink:href', '#land'); /* draw the boundaries */ for (i = 1; i < 4; i++) { vis.append('path').datum(topojson.mesh(data, data.objects[i], (function(a, b) { return a.properties.prefix.slice(0, -1) === b.properties.prefix.slice(0, -1); }))).attr('d', path_generator).attr('class', 'boundary').style('stroke-width', "" + (0.7 / (i * i)) + "px"); } /* draw the labels */ return vis.selectAll('.label').data(topojson.feature(data, data.objects[1]).features.concat(topojson.feature(data, data.objects[2]).features, topojson.feature(data, data.objects[3]).features)).enter().append('text').attr('class', 'label').attr('dy', '0.35em').attr('transform', (function(d) { var centroid; centroid = path_generator.centroid(d); return "translate(" + centroid[0] + "," + centroid[1] + ") scale(" + (20 / (Math.pow(d.properties.prefix.length, 1.7))) + ")"; })).text(function(d) { return d.properties.prefix; }); }); }; }).call(this);