// Setup var width = 960; var height = 500; var radius = 2.5; var svg = d3.select('svg'); // append a group for zoomable content var zoom_group = svg.append('g'); // define a zoom behavior var zoom = d3.behavior.zoom() .scaleExtent([1,4]) // min-max zoom .on('zoom', function() { // whenever the user zooms, // modify translation and scale of the zoom group accordingly zoom_group.attr('transform', 'translate('+zoom.translate()+')scale('+zoom.scale()+')'); // semantic zooming zoom_group.selectAll('.place') .attr('r', radius/zoom.scale()); }); // bind the zoom behavior to the main SVG svg.call(zoom); // Lambert equal-area projection - EU standard for statistical maps projection = d3.geo.azimuthalEqualArea() .clipAngle(180 - 1e-3) .scale(160000) .rotate([-10.277475, -42.789034, 0]) .translate([width / 2, height / 2]) .precision(0.1); path_generator = d3.geo.path() .projection(projection); var graticule = d3.geo.graticule() .step([1,1]) .extent([0, 20, 30, 60]); // draw the graticule zoom_group.append('path') .datum(graticule) .attr('class', 'graticule') .attr('d', path_generator); var colorify = d3.scale.category10() .domain(['restaurant', 'attraction', 'poi', 'accommodation']); var data_url = 'http://wafi.iit.cnr.it/openervm/api/getPlacesByArea?S=42.666&N=42.912&W=10&E=10.5'; var geo_url = 'http://wafi.iit.cnr.it/webvis/italiastat/data/istat/2011/reg2011.topo.json'; d3.json(geo_url, function(geo) { var regions = topojson.feature(geo, geo.objects.reg2011); zoom_group.selectAll('.region') .data(regions.features) .enter().append('path') .attr('class', 'region') .attr('d', path_generator); d3.json(data_url, function(data) { zoom_group.selectAll('.place') .data(data) .enter().append('circle') .attr('class', 'place') .attr('r', radius) .attr('fill', function(d){return colorify(d.category);}) .attr('transform', function(d){ var p = projection([d.lng, d.lat]); return 'translate('+p[0]+','+p[1]+')'; }); }); });