UPDATE: I have posted and accepted a fully working solution in the answers section. Any code in this section is to be used as reference for comparison to your own NON-WORKING code, but is not to be used as the solution.
I'm building a dashboard and using d3.js to add a world map that will plot tweets in real time based on geo location.
The world.json file referenced in the d3.json() line is downloadable HERE (it's called world-countries.json).
The map is on the page as an SVG container and is rendered using d3.
Below are the relevant code slices.
<div id="mapContainer"> <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="500"></svg> </div>
#mapContainer svg { display:block; margin:0 auto; } #mapContainer path { fill:#DDD; stroke:#FFF; }
// generate US plot function draw() { var map = d3.select("svg"); var width = $("svg").parent().width(); var height = $("svg").parent().height(); var projection = d3.geo.equirectangular().scale(185).translate([width/2, height/2]); var path = d3.geo.path().projection(projection); d3.json('plugins/maps/world.json', function(collection) { map.selectAll('path').data(collection.features).enter() .append('path') .attr('d', path) .attr("width", width) .attr("height", height); }); } draw(); latestLoop();
$(window).resize(function() { draw(); });
UPDATE: I have scaled the map to an acceptable size (for my particular browser size), but it still will not scale and center when I change the size of the window. IF, however, I resize the window, then hit refresh, then the map will be centered once the page is reloaded. However, since the scale is static, it is not scaled properly.
COMPLETE SOLUTION:
Here's the solution which will resize the map AFTER the user has released the edge of the window to resize it, and center it in the parent container.
<div id="mapContainer"></div>
function draw(ht) { $("#mapContainer").html("<svg id='map' xmlns='http://www.w3.org/2000/svg' width='100%' height='" + ht + "'></svg>"); map = d3.select("svg"); var width = $("svg").parent().width(); var height = ht; // I discovered that the unscaled equirectangular map is 640x360. Thus, we // should scale our map accordingly. Depending on the width ratio of the new // container, the scale will be this ratio * 100. You could also use the height // instead. The aspect ratio of an equirectangular map is 2:1, so that's why // our height is half of our width. projection = d3.geo.equirectangular().scale((width/640)*100).translate([width/2, height/2]); var path = d3.geo.path().projection(projection); d3.json('plugins/maps/world.json', function(collection) { map.selectAll('path').data(collection.features).enter() .append('path') .attr('d', path) .attr("width", width) .attr("height", width/2); }); } draw($("#mapContainer").width()/2);
$(window).resize(function() { if(this.resizeTO) clearTimeout(this.resizeTO); this.resizeTO = setTimeout(function() { $(this).trigger('resizeEnd'); }, 500); }); $(window).bind('resizeEnd', function() { var height = $("#mapContainer").width()/2; $("#mapContainer svg").css("height", height); draw(height); });
The selection object is an multidimensional array, although in most cases it will probably have only one object in it. That object has a "clientWidth" field that tells you how wide its parent is.
So you can do this:
var selection = d3.select("#chart"); width = selection[0][0].clientWidth;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With