2016-12-09 2 views
2

Ich versuche eine Version von Mike Bostocks Spinning Globe zu implementieren und Länderlabels zu überlagern. Dies wurde erfolgreich hier erreicht: http://bl.ocks.org/dwtkns/4686432Etiketten können nicht "hinter" gesponnen werden D3 Globe

Leider kann ich die Etiketten nicht verstecken, die hinter den Globus fallen sollten. Die Methode, die ich ausprobiert habe, ist es, den Abstand zwischen Pfadschwerpunkten und der Mittelposition des Globus zu berechnen. Aber aus irgendeinem Grund der Code die falschen Etiketten zu sein inkonsequent und versteckt scheint ...

Dies ist das Bit des Codes ist, dass die Etiketten versteckt:

function position_labels() { 
    var centerPos = projection.invert([width/2, height/2]); 

    var arc = d3.geo.greatArc(); 

    // update: update path projection before applying it to labels position 
    path.projection(projection); 
    svg.selectAll(".label") 
    .attr("transform", function(d) { 

     return "translate(" + path.centroid(d) + ")"; 
    }) 
    .style("display", function(d) { 
     var d = arc.distance({ 
     source: path.centroid(d), 
     target: centerPos 
     }); 
     return (d > 1.57) ? 'inline' : 'none'; 
    }) 
} 

Ich habe meine Arbeit in der folgenden jsfiddle gespeichert -bitte lassen Sie mich weiß, was ich tue, falsch: http://jsfiddle.net/Guill84/kh3kegsy/

UPDATE:

das ist eine Momentaufnahme des Problems, bei dem Ländername nach wie vor rund um die Karte zu schweben scheint. Sehen Sie bitte meinen Kommentar unten für weitere Erklärung:

Russia problem

+0

In der Geige verwenden Sie path.centroid(), die Koordinaten in Svg Koordinatenraum zurückgibt. Dies funktioniert für die Platzierung der Etiketten. Sie benötigen jedoch die geografischen Koordinaten des Schwerpunkts, um festzustellen, ob ein Etikett sichtbar sein soll. Das Problem, wie ich es mir vorstelle, ist, dass projection.invert (path.centroid (d)), wenn man diesen Ansatz verwendet, die sichtbare geographische Koordinate an einer gegebenen svg-Koordinate zurückgibt, was bedeutet, dass alle Beschriftungen als sichtbar angesehen werden. Auch messen Sie Abstand von [190,190] auf der Svg statt [400,400], da Ihre Breite und Höhe 800 Pixel sind, basierend auf der Geige. –

Antwort

2

Ich bemerkte eine potenzielle Hürde bei der Verwendung von Koordinaten-Label Sichtbarkeit in meinem Kommentar oben zu bestimmen. Es gibt jedoch noch eine andere Möglichkeit festzustellen, ob ein Label sichtbar sein soll: Ermitteln, ob der Svg-Pfad eines Landes ein Attribut "d" hat, das nicht null ist.

Zuerst ids müssen richtig eingestellt werden, die derzeit d.properties.name Leerzeichen enthält, so ids mit der Einstellung:

.attr("id", function(d) { return d.properties.name.split(' ').join('_'); }) 

wird zur besseren Identifizierung von Orten ermöglichen wie das Vereinigte Königreich und die Vereinigten Staaten von Amerika .

Durch die Auswahl jedes Pfades basierend auf ID können wir sehen, ob es irgendwelche Daten hat, die seine Form definieren. Wenn dies nicht angezeigt wird, ist die Eigenschaft 'd' des Pfads null.

if (d3.select("#"+d.properties.name.split(' ').join('_')).attr('d') != null) { 
     return 'inline'; 
    } 
    else { 
     return 'none'; 
    } 

Aktualisiert Geige: here

einen anderen Text Anker verwenden könnte auch Ihren Text besser Zentrum:

.style("text-anchor","middle"); 

Fiddle mit Text Anker Mitte: here

--- Update --- Während der Code oben die Beschriftungen für nicht gezeichnete Länder (vollständig hinter dem Globus) verbergen, wenn jeder Teil des Landes wird gezeichnet, dann wird ein Label erstellt. Viele Probleme in diesem Zusammenhang können behoben werden, indem Sie keine Etiketten mit einer bestimmten Entfernung von der Mitte zeichnen: fiddle, as mentioned in comment below.

Für einige große Länder wie Russland kann der geografische Schwerpunkt (und somit der Beschriftungsort) in den angegebenen Radius fallen und wird gezogen, wenn ein kleiner Streifen des Landes gerendert wird. Wenn dies geschieht, wird der geografische Schwerpunkt und nicht der Schwerpunkt svg verwendet, um das Land zu kennzeichnen. In diesen Fällen befindet sich der geografische Schwerpunkt auf der anderen Seite der Erde, aber so, als ob er auf der sichtbaren Seite wäre.

Auch im Fall von Frankreich, svg Schwerpunkt und geographischer Schwerpunkt werden problematisch sein: France

ein paar Methoden verwendet werden könnte, in Hin- und Herschalten von Etikett zu unterstützen, wie zum Beispiel Datenverarbeitung und Aufzeichnung der geografischen Schwerpunkte in die geografischen Daten und die Winkelentfernung vom Kartenprojektionszentrum zum Anzeigen/Verbergen der Beschriftungen. Im Falle Frankreichs wäre eine Aufspaltung Guayanas sinnvoll.

Ohne die Daten zu ändern, kann ein anderes Kriterium verwendet werden, um auszuwählen, welche Labels sichtbar sein sollen: Sehen Sie, ob der Mittelpunkt der Bounding Box des Landes in der Nähe des Kartenrandes liegt. Es fügt eine zusätzliche Schicht der Berechnung, aber wenn jedes Kriterium nur bei Bedarf aktiviert ist, sollte es in Ordnung sein: http://jsfiddle.net/0ptcy7f3/1/

var country = d3.select("#"+d.properties.name.split(' ').join('_')); 
// Exclude labels this far from center: 
var r = 350; 

// Check to see if the country has a path visible as before 
if (country.attr('d') != null) { 

    // Then check to see if the bounding box 
    // for the country as drawn is far from center 
    var BB = country.node().getBBox(); 
    var x = (BB.x + (BB.x + BB.width))/2; 
    var y = (BB.y + (BB.y + BB.height))/2; 

    if (((width-x)*(width-x) + (height-y)*(height-y)) < (r * r)) { 
     // And ensure the geographic centroid is also not on the edge: 
     center = path.centroid(d); 
     x = center[0]; 
     y = center[1]; 
    if (((width-x)*(width-x) + (height-y)*(height-y)) < (r * r)) { 
      return 'inline'; 
    } 
    else { 
      return 'none'; 
    } 
    } 
else { return 'none'; } 
else { return 'none'; } 

Der Fall von Frankreich wird nicht angesprochen, da sie geografischer Weg sind, schließt ein Guayana. Ein spezieller Fall könnte in den Code eingebaut werden, um das Etikett zu einem bestimmten Ort zu zwingen und diesen Ort als einen gültigen Ort auszuwerten. Andernfalls müssen die Daten bearbeitet werden. Dieses Update sollte sich um Russland oder andere große/lange Länder kümmern.

Eine Änderung, die vorgenommen werden könnte, ist das Ändern des Ausschlussradius, wenn die Karte vergrößert wird (oder nicht, wenn die Karte den gesamten Rahmen ausfüllt).

+1

Beim Anschauen sieht es so aus, als ob ein Land teilweise sichtbar ist, der Schwerpunkt enthält auch den versteckten Bereich, so dass die Beschriftung etwas an den Rändern liegen kann. Um diese Beschriftungen ebenfalls zu entfernen, könntest du etwas wie in dieser Geige versuchen : http://jsfiddle.net/6pwcrasf/ –

+0

Ihre Lösung ist sehr elegant und genau das, was ich gesucht habe. Ich habe jedoch einen Fehler bemerkt ... wie einige Ländernamen scheinen um die Karte zu schweben, unabhängig davon, ob das Land sichtbar ist oder nicht .. Frankreich und Russland sind zwei gute Beispiele, und ich frage mich, ob dies nicht (a) die Größe des Landes und (b) Vieleckkomplexität in Überseegebieten, usw.? Ich habe ein Bild im OP hinzugefügt, um zu zeigen, was ich meine. – Noobster

+0

Ich denke, das sind die beiden Gründe für Ärger, und ich denke, es kann eine Kombination aus beidem sein, zum Beispiel umfasst Frankreichs Vieleck Französisch-Guayana in Südamerika (und wahrscheinlich Dutzende anderer Gebiete). Im Fall von Russland denke ich, dass es am Rande der Karte eine kleine Menge des Landes gibt, und da das Land so groß ist, kann der geographische Schwerpunkt leicht in den Grundausschlussradius fallen, den ich in dem obigen Kommentar eingerichtet habe . Hmm, darüber muss ich noch etwas nachdenken. –

Verwandte Themen