// set multiple attrs with an object var set_attrs = function(object, hash) { for (var key in hash) { object.attr(key, hash[key]); } }; window.onload = function() { merc = d3.geo.mercator() .scale(400) .translate([200, 200]); albers = d3.geo.albers() .scale(60) .translate([180, 250]); ortho = d3.geo.azimuthal() .scale(140) .origin([-71.03, 0]) .mode("orthographic") .translate([600, 200]); var merc_path = d3.geo.path() .projection(merc); var albers_path = d3.geo.path() .projection(albers); var ortho_path = d3.geo.path() .projection(ortho); var merc_attrs = { 'class': 'merc', r: 1, transform: function(d) { return 'translate(' + merc(d).join(',') + ')'; } }; var albers_attrs = { 'class': 'albers', r: 1, transform: function(d) { return 'translate(' + albers(d).join(',') + ')'; } }; var ortho_attrs = { 'class': 'ortho', r: 1, transform: function(d) { return 'translate(' + ortho(d).join(',') + ')'; } }; var connection_attrs = { 'class': 'connect', 'd': function(d) { return 'M' + albers(d).join(' ') + 'L' + ortho(d).join(' ') + 'z'; } }; var w = 780, h = 500; var svg = d3.select("#chart").append("svg:svg") .attr("width", w) .attr("height", h); var points = []; for (var lon = -180; lon < 180; lon += 10) { for (var lat = -90; lat < 90; lat += 10) { points.push([lon, lat]); } } svg.selectAll("circle.merc") .data(points) .enter() .append('svg:circle') .call(set_attrs, albers_attrs); var ortho_drawn = svg.selectAll("circle.ortho") .data(points) .enter() .append('svg:circle') .call(set_attrs, ortho_attrs); var connections = svg.selectAll("path.connect") .data(points) .enter() .append('svg:path') .call(set_attrs, connection_attrs); svg.on('mousemove', function() { var x = ((d3.event.pageX / w) * 360) - 180; var y = ((d3.event.pageY / h) * 360) - 180; ortho.origin([x, y]); ortho_drawn.attr('transform', function(d) { return 'translate(' + ortho(d).join(',') + ')'; }); connections.attr('d', function(d) { return 'M' + albers(d).join(' ') + 'L' + ortho(d).join(' ') + 'z'; }); }); };