Actuellement en d3, si vous avez un objet geoJSON que vous allez dessiner, vous devez le mettre à l'échelle et le traduire afin de l'obtenir à la taille souhaitée et de le traduire afin de le centrer. C'est une tâche très fastidieuse d'essais et d'erreurs, et je me demandais si quelqu'un connaissait un meilleur moyen d'obtenir ces valeurs?
Donc par exemple si j'ai ce code
var path, vis, xy;
xy = d3.geo.mercator().scale(8500).translate([0, -1200]);
path = d3.geo.path().projection(xy);
vis = d3.select("#vis").append("svg:svg").attr("width", 960).attr("height", 600);
d3.json("../../data/ireland2.geojson", function(json) {
return vis.append("svg:g")
.attr("class", "tracts")
.selectAll("path")
.data(json.features).enter()
.append("svg:path")
.attr("d", path)
.attr("fill", "#85C3C0")
.attr("stroke", "#222");
});
Comment diable puis-je obtenir .scale (8500) et .translate ([0, -1200]) sans aller petit à petit?
Réponses:
Ce qui suit semble faire à peu près ce que vous voulez. La mise à l'échelle semble être correcte. Lors de son application à ma carte, il y a un petit décalage. Ce petit décalage est probablement dû au fait que j'utilise la commande translate pour centrer la carte, alors que je devrais probablement utiliser la commande center.
Dans du code:
la source
projection.fitSize([width, height], geojson)
( docs API ) - voir la réponse de @dnltsk ci-dessous.Ma réponse est proche de celle de Jan van der Laan, mais vous pouvez simplifier légèrement les choses car vous n'avez pas besoin de calculer le centre de gravité géographique; vous n'avez besoin que du cadre de sélection. Et, en utilisant une projection unitaire non mise à l'échelle et non traduite, vous pouvez simplifier les calculs.
La partie importante du code est la suivante:
Après avoir compilé le cadre de délimitation de l'entité dans la projection unitaire, vous pouvez calculer l' échelle appropriée en comparant le rapport hauteur / largeur du cadre englobant (
b[1][0] - b[0][0]
etb[1][1] - b[0][1]
) au rapport hauteur / largeur du canevas (width
etheight
). Dans ce cas, j'ai également mis à l'échelle le cadre de délimitation à 95% du canevas, plutôt qu'à 100%, il y a donc un peu plus de place sur les bords pour les traits et les caractéristiques environnantes ou le remplissage.Ensuite, vous pouvez calculer la translation en utilisant le centre du cadre de sélection (
(b[1][0] + b[0][0]) / 2
et(b[1][1] + b[0][1]) / 2
) et le centre du canevas (width / 2
etheight / 2
). Notez que puisque la boîte englobante est dans les coordonnées de la projection unitaire, elle doit être multipliée par l'échelle (s
).Par exemple, bl.ocks.org/4707858 :
Il y a une question connexe: comment zoomer sur une caractéristique spécifique d'une collection sans ajuster la projection, c'est -à- dire combiner la projection avec une transformation géométrique pour effectuer un zoom avant et arrière. Cela utilise les mêmes principes que ci-dessus, mais le calcul est légèrement différent car la transformation géométrique (l'attribut SVG "transform") est combinée avec la projection géographique.
Par exemple, bl.ocks.org/4699541 :
la source
* 500
c'est étranger ici ... aussi,b[1][1] - b[0][0]
devrait êtreb[1][1] - b[0][1]
dans le calcul de l'échelle.b.s = b[0][1]; b.n = b[1][1]; b.w = b[0][0]; b.e = b[1][0]; b.height = Math.abs(b.n - b.s); b.width = Math.abs(b.e - b.w); s = .9 / Math.max(b.width / width, (b.height / height));
Avec d3 v4 ou v5, cela devient beaucoup plus facile!
et enfin
Appréciez, Cheers
la source
d3v4
depuis un moment et je viens de découvrir cette méthode.g
vient-il? Est-ce le conteneur svg?g
devrait être<g></g>
tagJe suis nouveau dans d3 - je vais essayer d'expliquer comment je le comprends mais je ne suis pas sûr d'avoir tout bien compris.
Le secret est de savoir que certaines méthodes opéreront sur l'espace cartographique (latitude, longitude) et d'autres sur l'espace cartésien (x, y sur l'écran). L'espace cartographique (notre planète) est (presque) sphérique, l'espace cartésien (écran) est plat - pour cartographier l'un sur l'autre, vous avez besoin d'un algorithme appelé projection . Cet espace est trop court pour approfondir le sujet fascinant des projections et comment elles déforment les caractéristiques géographiques afin de transformer sphérique en plan; certains sont conçus pour conserver les angles, d'autres pour conserver les distances et ainsi de suite - il y a toujours un compromis (Mike Bostock a une énorme collection d'exemples ).
En d3, l'objet de projection a une propriété / setter center, donnée en unités cartographiques:
Il y a aussi la translation, donnée en pixels - où le centre de projection se situe par rapport au canevas:
Lorsque je souhaite centrer une entité dans le canevas, j'aime définir le centre de projection au centre de la zone de délimitation de l'entité - cela fonctionne pour moi lorsque j'utilise mercator (WGS 84, utilisé dans Google Maps) pour mon pays (Brésil), jamais testé en utilisant d'autres projections et hémisphères. Vous devrez peut-être faire des ajustements pour d'autres situations, mais si vous appliquez ces principes de base, tout ira bien.
Par exemple, étant donné une projection et un chemin:
La
bounds
méthode frompath
renvoie le cadre de sélection en pixels . Utilisez-le pour trouver la bonne échelle, en comparant la taille en pixels avec la taille en unités de la carte (0,95 vous donne une marge de 5% sur le meilleur ajustement pour la largeur ou la hauteur). Géométrie de base ici, calculant la largeur / hauteur du rectangle en fonction des coins diagonalement opposés:Utilisez la
d3.geo.bounds
méthode pour trouver la boîte englobante en unités de carte:Définissez le centre de la projection sur le centre du cadre de sélection:
Utilisez la
translate
méthode pour déplacer le centre de la carte vers le centre du canevas:Vous devriez maintenant avoir la fonction au centre de la carte agrandie avec une marge de 5%.
la source
Il y a un centre () méthode , vous pouvez utiliser une paire qui accepte latitude / longitude.
D'après ce que je comprends, translate () n'est utilisé que pour déplacer littéralement les pixels de la carte. Je ne sais pas comment déterminer quelle est l'échelle.
la source
En plus de Centrer une carte dans d3 à partir d'un objet geoJSON , notez que vous pouvez préférer
fitExtent()
plutôt quefitSize()
si vous souhaitez spécifier un remplissage autour des limites de votre objet.fitSize()
définit automatiquement ce remplissage à 0.la source
Je cherchais sur Internet un moyen simple de centrer ma carte et je me suis inspiré de la réponse de Jan van der Laan et de mbostock. Voici un moyen plus simple d'utiliser jQuery si vous utilisez un conteneur pour le svg. J'ai créé une bordure de 95% pour le rembourrage / bordures, etc.
Si vous recherchez une mise à l'échelle exacte, cette réponse ne fonctionnera pas pour vous. Mais si comme moi, vous souhaitez afficher une carte qui se centralise dans un conteneur, cela devrait suffire. J'essayais d'afficher la carte Mercator et j'ai trouvé que cette méthode était utile pour centraliser ma carte, et je pouvais facilement couper la partie Antarctique puisque je n'en avais pas besoin.
la source
Pour faire un panoramique / zoomer la carte, vous devez regarder superposer le SVG sur Leaflet. Ce sera beaucoup plus facile que de transformer le SVG. Voir cet exemple http://bost.ocks.org/mike/leaflet/ puis Comment changer le centre de la carte dans le dépliant
la source
Avec la réponse de mbostocks et le commentaire de Herb Caudill, j'ai commencé à rencontrer des problèmes avec l'Alaska depuis que j'utilisais une projection Mercator. Je dois noter que pour mes propres besoins, j'essaie de projeter et de centrer les États américains. J'ai trouvé que je devais marier les deux réponses avec la réponse de Jan van der Laan à l'exception suivante pour les polygones qui chevauchent des hémisphères (polygones qui finissent avec une valeur absolue pour Est - Ouest supérieure à 1):
configurer une projection simple dans mercator:
projection = d3.geo.mercator (). scale (1) .translate ([0,0]);
créer le chemin:
chemin = d3.geo.path (). projection (projection);
3. fixer mes limites:
4.Ajoutez une exception pour l'Alaska et les États qui chevauchent les hémisphères:
J'espère que ça aide.
la source
Pour les personnes qui souhaitent ajuster verticalement et horizontalement, voici la solution:
la source
Comment j'ai centré un Topojson, où je devais retirer la fonctionnalité:
la source