D3js: Automatique des étiquettes de placement pour éviter les chevauchements? (force de répulsion)

Comment faire pour appliquer une force de répulsion sur la carte de labels, de sorte qu'ils trouvent leur place automatiquement ?


Bostock' "nous allons Faire une Carte"

Mike Bostock est Nous allons Faire une Carte (capture d'écran ci-dessous). Par défaut, les étiquettes sont les coordonnées du point et des polygones/multipolygons de path.centroid(d) + simple à gauche ou à droite aligner, donc ils sont souvent en conflit.

D3js: Automatique des étiquettes de placement pour éviter les chevauchements? (force de répulsion)

Label à la main stages

Une amélioration J'ai rencontré nécessite d'ajouter un humain en fait IF de bugs, et d'en ajouter autant que nécessaire, par exemple :

.attr("dy", function(d){ if(d.properties.name==="Berlin") {return ".9em"} })

L'ensemble du devenir de plus en plus sale que le nombre d'étiquettes à reajust augmentation :

//places's labels: point objects
svg.selectAll(".place-label")
.data(topojson.object(de, de.objects.places).geometries)
.enter().append("text")
.attr("class", "place-label")
.attr("transform", function(d) { return "translate(" + projection(d.coordinates) + ")"; })
.attr("dy", ".35em")
.text(function(d) { if (d.properties.name!=="Berlin"&&d.properties.name!=="Bremen"){return d.properties.name;} })
.attr("x", function(d) { return d.coordinates[0] > -1 ? 6 : -6; })
.style("text-anchor", function(d) { return d.coordinates[0] > -1 ? "start" : "end"; });
//districts's labels: polygons objects.
svg.selectAll(".subunit-label")
.data(topojson.object(de, de.objects.subunits).geometries)
.enter().append("text")
.attr("class", function(d) { return "subunit-label " + d.properties.name; })
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
.attr("dy", function(d){
//handmade IF
if( d.properties.name==="Sachsen"||d.properties.name==="Thüringen"|| d.properties.name==="Sachsen-Anhalt"||d.properties.name==="Rheinland-Pfalz")
{return ".9em"}
else if(d.properties.name==="Brandenburg"||d.properties.name==="Hamburg")
{return "1.5em"}
else if(d.properties.name==="Berlin"||d.properties.name==="Bremen")
{return "-1em"}else{return ".35em"}}
)
.text(function(d) { return d.properties.name; });

Besoin d'une meilleure solution

C'est juste pas gérable pour les grandes cartes et des jeux d'étiquettes. Comment ajouter de la force repulsions de ces deux classes: .place-label et .subunit-label?

Cette question est tout à fait un remue-méninges que je n'ai pas de date limite, mais je suis assez curieux à ce sujet. Je pensais à cette question de base D3js mise en œuvre de Migurski/Dymo.py. Dymo.py s'README.md ensemble de la documentation d'un grand ensemble d'objectifs, à partir de laquelle sélectionner la base des besoins et des fonctions (20% de l'activité, 80% du résultat).

  1. Placement Initial: Bostock donner un bon départ avec gauche/droite positionnement par rapport à la geopoint.
  2. Inter-étiquettes de répulsion: approche différente sont possibles, Lars & Navarrc proposé un chacun,
  3. Étiquettes annihilation: Une étiquette d'annihilation de la fonction lorsque l'un label global de répulsion est trop intense, car coincé entre autres labels, avec la priorité à l'anéantissement de l'être aléatoire ou en fonction d'un population données de la valeur, que nous pouvons obtenir par NaturalEarth de l' .shp fichier.
  4. [Luxe] d'Étiquette à des points de répulsion: avec points fixes et mobiles des étiquettes. Mais c'est plutôt un luxe.

J'ignore si l'étiquette de la répulsion va travailler à travers des couches et des classes d'étiquettes. Mais pour obtenir des pays les étiquettes et les villes étiquettes non cumul peut être un luxe.

  • Je pense que l'ajout de la force de répulsion à l'endroit des étiquettes peut rendre certaines étiquettes aller hors de leur région respective. Autre chose à considérer est que les différents types d'étiquettes peuvent se chevaucher dans certaines cartes, le nom d'une ville peut être au-dessus du nom du pays, avec de très distint polices bien. Je pense que la solution définitive peut être plus complexe que simplement ajouter de la répulsion.
  • J'ai utilisé une force de mise en page pour positionner les étiquettes ici: larsko.org/v/igdp/index-alt.html Votre cas est plus complexe, car elle implique deux dimensions, mais vous pourriez être en mesure de réutiliser une partie du code.
  • Tout d'abord, comment appliquer la répulsion sur mes articles. Plus tard, la force peut être subtile. Il a besoin d'une répulsion diminue rapidement avec la distance, le type de R = 1/x. Cet ajustement sera un autre problème.
  • J'ai mis en place une démo de cette stratégie. Il n'est pas parfait, mais il peut aider. bl.ocks.org/pnavarrc/5913636
  • Je sais que ce n'est pas la force de répulsion liés, mais comme Mike Bostock a souligné dans le tutoriel, il y a ce script github.com/migurski/Dymo cela devrait faire l'affaire (je n'étais pas capable de le faire fonctionner tho, j'ai même posté une question ici pour avoir des conseils mais bon j'espère que vous pouvez!)
  • Tout puissant, Dymo.py est un Python approche qui est tout à fait contre-productif au sein de D3js / client web-cartographie de l'écosystème. Je suis plutôt de l'ouverture d'un à long terme pour parler d'une pure D3js approche, probablement plus basique, mais efficace et suffisante.

InformationsquelleAutor Hugolpz | 2013-07-02