Zoom e região MKMapView

85

Estou familiarizado com o uso da API Javascript do Google Maps. Recentemente, comecei a usar o framework MapKit para um projeto de iphone, mas estou tendo dificuldade em descobrir como aumentar o zoom e definir uma região no mapa.

Na API do Google Maps, eu costumava usar níveis de zoom inteiros como 8, 9, 10 junto com a função direta setZoom (). O único método equivalente que posso ver na estrutura MapKit é setRegion: animated. Pelo que entendi, preciso definir os valores "delta" de latitude e longitude da extensão de uma região para especificar o nível de zoom. Mas eu realmente não tenho ideia do que esses valores representam (eu li a documentação).

Quando eu uso um delegado MKMapView e rastreio os valores de amplitude no método de delegado regionDidChange, os resultados não parecem se correlacionar. Tudo bem quando eu afasto o zoom e vejo que os valores de span delta estão aumentando conforme especificado na documentação. Mas, de repente, arrasto o mapa sem aplicar zoom e os valores delta tornam-se 0,0.

Alguém pode explicar qual é o ponto de referência para esses span e delta? Ou existe algum algoritmo para converter um nível de zoom inteiro (como 9) para esses valores delta?

Como pergunta bônus, há alguma maneira de especificar um nível de zoom mínimo-máximo em um MKMapView :)

obrigado

cocoatoucher
fonte

Respostas:

134

Em primeiro lugar, MKMapView não usa / tem um conjunto predefinido de níveis de zoom como o Google Maps faz.

Em vez disso, a área visível de um MKMapView é descrita usando MKCoordinateRegion , que consiste em dois valores:

  1. centro (o ponto central da região), e
  2. span (o tamanho da área visível ao redor do centro).

O ponto central deve ser óbvio (é o ponto central da região).

No entanto, span (que é um MKCoordinateSpan ) consiste em:

  1. latitudeDelta (a distância vertical representada pela região), e
  2. longitudeDelta (a distância horizontal representada pela região).

Um breve exemplo. Aqui está um brinquedo MKCoordinateRegion:

  1. Centro:
    • latitude: 0
    • longitude: 0
  2. período:
    • latitudeDelta: 8
    • longitudeDelta: 6

A região pode ser descrita usando suas coordenadas mínimas e máximas da seguinte forma:

  1. coordenada min (ponto inferior esquerdo):
    • latitude: -4
    • longitude: -3
  2. coordenada máxima (ponto superior direito):
    • latitude: 4
    • longitude: 3

Portanto, você pode especificar os níveis de zoom em torno de um ponto central usando um MKCoordinateSpan de tamanho apropriado. Como uma aproximação dos níveis de zoom numéricos do Google, você pode fazer engenharia reversa dos tamanhos de span que o Google usa para um determinado nível de zoom e criar um span, de acordo. (O Google descreve suas regiões de visualização da mesma forma que MKMapView, como um centro + vão, então você pode extrair esses valores do Google Maps.)

Quanto a restringir a região, você pode jogar com este método delegado:

mapView:regionWillChangeAnimated

por exemplo, redimensionando a região de volta aos níveis de zoom permitidos. (Mais ou menos como as visualizações de tabela permitem que você role além da borda, mas depois o elástico volta ao lugar.) No entanto, sua milhagem pode variar, já que não a usei para esse propósito.

A propósito, há correções / melhorias definitivas no OS 3.1 para aspectos do MapKit que estavam me causando problemas no 3.0.

Kelvin
fonte
@Kelvin, você pode descrever com mais detalhes como "fazer engenharia reversa dos tamanhos de span que o Google usa para um determinado nível de zoom e criar um span". Eu realmente preciso disso
Scofield Tran
118

Se você preferir usar níveis de zoom explícitos em vez de definir um MKCoordinateSpan, escrevi uma categoria que adiciona suporte para especificar o nível de zoom de um MKMapView. O código pode ser encontrado aqui .

Troy Brant
fonte
4
As postagens do blog de Troy me deram uma grande compreensão de como o mapkit e o Google Maps funcionam. Eu recomendo a leitura.
Aaron de
5
git: //github.com/jdp-global/MKMapViewZoom.git
johndpope
5

O intervalo está em graus de latitude e longitude. Existe um método para construir estruturas MKCoordinateRegion que leva distância, em vez disso. Pode ser que você esteja usando MKCoordinateRegionMakeWithDistance para especificar o intervalo e, ao verificar em regionDidChange, verá o intervalo de lat / long, que é como ele é armazenado em uma estrutura MKCoordinateRegion.

Até onde eu sei, os níveis de zoom de inteiro não estão disponíveis ou não são úteis ao trabalhar com MKMapKit. Eu pessoalmente prefiro usar os números de span, é mais flexível.

Você não pode especificar o zoom máximo e mínimo, e eu não conheço uma maneira de hackea-lo. MKMapKit é realmente muito fraco agora, estou muito desapontado com a falta de recursos.

Alice Isabelle
fonte
3

Uma comparação rápida dos níveis de zoom para um local usando maps.google.com, inspecionando a string de consulta do link, mostra que os valores de span dx e dy aumentam em um fator de 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
  ...
Ari Braginsky
fonte
2

A categoria de Brant no MKMapView funciona bem. No entanto, parece que ele não foi atualizado para oferecer suporte a dispositivos mais novos com telas de retina ao calcular mapSizeInPixels.

Pode ser corrigido substituindo esta linha:

CGSize mapSizeInPixels = mapView.bounds.size;

Com esta linha:

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