UPDATE: Ich habe im Antwortbereich eine voll funktionsfähige Lösung veröffentlicht und akzeptiert. Jeder Code in diesem Abschnitt dient als Referenz für den Vergleich mit Ihrem eigenen NICHT ARBEITENDEN Code, jedoch nicht als Lösung.
Ich baue ein Dashboard und verwende d3.js, um eine Weltkarte hinzuzufügen, die Tweets in Echtzeit basierend auf dem geografischen Standort plottet.
Die world.json -Datei, auf die in der Zeile d3.json () verwiesen wird, kann HERE heruntergeladen werden (sie heißt world-countries.json).
Die Karte befindet sich auf der Seite als SVG-Container und wird mit d3 gerendert.
Nachfolgend finden Sie die relevanten 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: Ich habe die Karte auf eine akzeptable Größe (für meine bestimmte Browsergröße) skaliert, sie wird jedoch immer noch nicht skaliert und zentriert, wenn ich die Größe des Fensters ändere. Wenn ich jedoch das Fenster verkleinere, dann auf Aktualisieren klicke, wird die Karte zentriert, sobald die Seite neu geladen wird. Da die Waage jedoch statisch ist, wird sie nicht richtig skaliert.
KOMPLETTE LÖSUNG:
Hier ist die Lösung, bei der die Größe der Karte geändert wird, nachdem der Benutzer den Rand des Fensters freigegeben hat, um die Größe zu ändern und im übergeordneten Container zu zentrieren.
<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);
});
Das Auswahlobjekt ist ein mehrdimensionales Array, obwohl es in den meisten Fällen wahrscheinlich nur ein Objekt enthält. Dieses Objekt verfügt über ein Feld "clientWidth", in dem die Breite des übergeordneten Objekts angegeben wird.
So kannst du das machen:
var selection = d3.select("#chart");
width = selection[0][0].clientWidth;
Das sollte funktionieren:
<svg
xmlns="http://www.w3.org/2000/svg"
width="860"
height="500"
viewBox="0 0 860 500"
preserveAspectRatio="xMinYMin meet">
Die beste Wahl ist die kombinierte Verwendung des Seitenverhältnisses bei der normalen Definition der Breite und Höhe des d3-Diagramms. Das hat mir bei vielen Graphiken geholfen.
Schritt 1: Dynamisch die Höhe des divs ermitteln, an das der Graph angehängt werden soll.
Schritt 2: Breite als Seitenverhältnis in Bezug auf die dynamisch erfasste Höhe angeben.
var graph_div = document.getElementById(graph.divId);
graph.height = graph_div.clientHeight;
graph.width = (960/1200)*graph.height;
In d3 v4 könnten wir das tun
const projection = d3.geo.equirectangular().fitSize([width, height], geojson);
const path = d3.geo.path().projection(projection);
fitSize ist äquivalent zu
fitExtent([[0, 0], [width, height]], geojson)
füllen Sie frei, um Auffüllen hinzuzufügen