web-dev-qa-db-fra.com

Zoom et région MKMapView

Je suis familier avec l'utilisation de l'API Javascript de Google Maps. Récemment, j'ai commencé à utiliser le framework MapKit pour un projet iphone, mais j'ai du mal à comprendre le zoom et à définir une région sur la carte.

Dans l'API Google Maps, j'avais l'habitude d'utiliser des niveaux de zoom entiers comme 8, 9, 10 avec la fonction simple setZoom (). La seule méthode équivalente que je peux voir dans le framework MapKit est setRegion: animated. Si je comprends bien, je dois définir les valeurs de "delta" de latitude et de longitude d'une plage pour définir le niveau de zoom. Mais je n'ai vraiment aucune idée de ce que ces valeurs représentent (j'ai lu la documentation).

Lorsque j'utilise un délégué MKMapView et que je trace les valeurs d'intervalle dans les résultats de la méthode déléguée regionDidChange, il ne semble pas y avoir de corrélation. Ce n'est pas grave lorsque je fais un zoom arrière et que les valeurs delta span augmentent comme spécifié dans la documentation. Mais soudain, je fais glisser la carte sans zoomer et les valeurs delta deviennent 0,0.

Quelqu'un peut-il expliquer quel est le point de référence de ces travées et deltas? Ou existe-t-il un algorithme pour convertir un niveau de zoom entier (comme 9) en ces valeurs delta?

En bonus, existe-t-il un moyen de spécifier un niveau de zoom minimum-maximum sur un MKMapView :)

Merci

85
cocoatoucher

Tout d'abord, MKMapView n'utilise pas/n'a pas un ensemble de niveaux de zoom prédéfinis comme le fait Google Maps.

Au lieu de cela, la zone visible d'un MKMapView est décrite en utilisant MKCoordinateRegion, qui se compose de deux valeurs:

  1. centre (le point central de la région), et
  2. span (la taille de la zone visible autour du centre).

Le point central doit être évident (c'est le point central de la région.)

Cependant, span (qui est un MKCoordinateSpan) se compose de:

  1. latitudeDelta (la distance verticale représentée par la région), et
  2. longitudeDelta (la distance horizontale représentée par la région).

Un bref exemple. Voici un jouet MKCoordinateRegion:

  1. centre:
    • latitude: 0
    • longitude: 0
  2. envergure:
    • latitudeDelta: 8
    • longitudeDelta: 6

La région pourrait être décrite en utilisant ses coordonnées min et max comme suit:

  1. coordonnée min (point inférieur gauche):
    • latitude: -4
    • longitude: -3
  2. coordonnée maximale (point supérieur droit):
    • latitude: 4
    • longitude: 3

Ainsi, vous pouvez spécifier des niveaux de zoom autour d'un point central en utilisant un MKCoordinateSpan de taille appropriée. En tant qu'approximation des niveaux de zoom numérique de Google, vous pouvez inverser l'ingénierie des tailles de plage que Google utilise pour un niveau de zoom donné et créer une plage, en conséquence. (Google décrit leurs régions d'affichage de la même manière que MKMapView, en tant que centre + étendue, afin que vous puissiez extraire ces valeurs de Google Maps.)

Quant à restreindre la région, vous pouvez jouer avec cette méthode déléguée:

mapView:regionWillChangeAnimated

par exemple. en redimensionnant la région dans vos niveaux de zoom autorisés. (Un peu comme la façon dont les vues de table vous permettront de faire défiler le bord, mais qui reviendront ensuite en place.) Cependant, votre kilométrage peut varier, car je ne l'ai pas utilisé à cette fin.

btw, il y a des corrections/améliorations définitives dans OS 3.1 à des aspects de MapKit qui me posaient des problèmes dans 3.0.

134
Kelvin

Si vous préférez utiliser des niveaux de zoom explicites au lieu de définir un MKCoordinateSpan, j'ai écrit une catégorie qui ajoute la prise en charge de la spécification du niveau de zoom d'un MKMapView. Le code peut être trouvé ici .

118
Troy Brant

La portée est en degrés de latitude et de longitude. Il existe à la place une méthode pour construire des structures MKCoordinateRegion qui prend de la distance. Il se peut que vous utilisiez MKCoordinateRegionMakeWithDistance pour spécifier l'intervalle, puis lorsque vous le vérifiez dans regionDidChange, vous voyez à l'échelle lat/long, c'est ainsi qu'il est stocké dans une structure MKCoordinateRegion.

Pour autant que je sache, les niveaux de zoom entiers ne sont pas disponibles ou utiles du tout lorsque vous travaillez avec MKMapKit. Personnellement, je préfère utiliser les chiffres de durée, c'est plus flexible.

Vous ne pouvez pas spécifier de zoom max et min, et je ne connais pas de moyen de le pirater. MKMapKit est en fait assez faible en ce moment, je suis assez déçu par le manque de fonctionnalités.

4
Chase Johnson

Une comparaison rapide des niveaux de zoom pour un emplacement à l'aide de maps.google.com en inspectant la chaîne de requête de lien montre que les valeurs de dx et de dy span augmentent d'un facteur 2:

 (0.005334, 0.011834) starting span
 (0.010668, 0.023668) dx: x2, dy: x2 
 (0.021335, 0.047337) dx: x2, dy: x2
 (0.042671, 0.094671) dx: x2, dy: x2
  ...
3
Ari Braginsky

La catégorie de Brant sur MKMapView fonctionne bien. Cependant, il semble qu'il n'ait pas été mis à jour pour prendre en charge les appareils plus récents avec des écrans rétine lors du calcul de mapSizeInPixels.

Il peut être corrigé en remplaçant cette ligne:

CGSize mapSizeInPixels = mapView.bounds.size;

Avec cette ligne:

CGSize mapSizeInPixels = CGSizeMake(mapView.bounds.size.width * [UIScreen mainScreen].scale, mapView.bounds.size.height * [UIScreen mainScreen].scale);
2
Daniel