2015-05-17 3 views
6

Как сохранить курсор по центру на карте, пока я перемещаю (через Pan Gesture) другой вид по вертикали над картой, так что штифт остается над наложением (не фактическое наложение MapKit).Как удерживать штырь и карту по центру над перемещающимся наложением в MKMapView

См. Прикрепленные скриншоты для первого и последнего состояний.

У меня есть CGRect пространства между наложением и верхней частью экрана, когда пользовательская панорама вверх/вниз. Тем не менее, как я использую это, чтобы переместить карту и вывести ее при масштабировании на карту, когда пользователь поворачивается вверх ... и снова отбрасывает назад, когда пользователь поворачивается вниз, до сих пор не ускользнул от меня.

Я пробовал разные подходы, пытаясь настроить видимый прямоугольник, чтобы настроить рамку просмотра карты. Ответ может лежать в некотором MKMapRect/Регион обмане ..

Initial state

Final state with overlay panned upward

(Hand икона Freepik CC BY 3.0)

+0

вы пробовали 'setCenterCoordinate' подход? –

+0

Предполагается, что карта должна увеличиваться и уменьшаться при панорамировании наложения? – keithbhunter

+0

@keithbhunter Да, внутрь, когда вы катитесь вверх и наружу, когда вы катитесь вниз. – Aodh

ответ

4
class ViewController: UIViewController { 

    @IBOutlet weak var mapView: MKMapView! 
    @IBOutlet weak var slidingView: UIView! 
    @IBOutlet weak var slidingViewHeight: NSLayoutConstraint! 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.reloadMap() 
     let pan = UIPanGestureRecognizer(target: self, action: "viewDidPan:") 
     self.slidingView.addGestureRecognizer(pan) 
    } 

    func reloadMap() { 
     let coordinate = CLLocationCoordinate2D(latitude: 37.332363, longitude: -122.030805) 
     let height = Double(self.mapView.frame.size.height) 
     let regionDistance = 0.3 * height * height // random multiplier and exponential equation for scaling 
     let region = MKCoordinateRegionMakeWithDistance(coordinate, regionDistance, regionDistance) 
     self.mapView.setRegion(region, animated: false) 
    } 

    func viewDidPan(panGesture: UIPanGestureRecognizer) { 
     let location = panGesture.locationInView(self.view) 
     self.slidingViewHeight.constant = self.view.frame.size.height - location.y 
     self.reloadMap() 
    } 

} 

Для установки мнение, разместить карту вид и UIView на вашем контроллере. Используйте автозапуск, чтобы вывести левую, верхнюю и правую стороны карты в супервизор. Затем прикрепите нижнюю часть карты к верхней части UIView. Затем закрепите левую, нижнюю и правую стороны поля UIView. Наконец, установите ограничение по высоте на UIView на то, что вы хотите инициализировать. Это значение высоты будет изменено, когда пользователь перетащит представление. Это позволяет UIView расти, как нам нравится, и одновременно успокаивать автозапуск.

Добавить @IBOutlet в контроллер представления для просмотра карты, на и ограничение высоты UIViewUIView «s, как в приведенном выше коде. Свойство regionDistance - это то, что делает магию масштабирования здесь. Это экспоненциальное уравнение (которое я сделал случайным образом), которое будет вычислять область как для большего, так и для меньшего размера в зависимости от высоты отображения карты. reloadMap() использует это, чтобы обновить масштаб карты. Связывание всего этого - это UIPanGestureRecognizer на UIView, что и определяет высоту UIView, вызывая действие масштабирования на карте.

Pitfall: Это заставляет карту обновлять регион быстрее, чем может загружать регион, что делает его очень напряженным. Вероятно, есть способы обойти это. Получите творческий подход.

Координата, которую я использовал в примере, является штаб-квартирой Apple.

Apple's HQ

5

На самом деле, код keithbhunter является медленным, потому что, помимо обновления региона быстрее, чем он может загрузить его, карта также меняется по высоте, которая вызывает дополнительные накладные расходы!

Я обновил код, чтобы он работал ровно.

С помощью этого кода я делаю, чтобы карта выглядела одинакового размера, но вместо этого я перемещаю точку центра, чтобы компенсировать высоту скользящего вида.

Для этого кода вам необходимо изменить настройку keithbhunter так, чтобы нижнее ограничение mapView полностью привязано к нижней части супервизора (а не к slideView (так, чтобы mapView всегда был того же размера, что и супер-просмотр) . в остальном установка такая же.

enter image description here

Также можно настроить степень увеличения с переменной maxMetersDistance

Здесь я всегда центровки на Эйфель башни

enter image description here enter image description here

import UIKit 
import MapKit 

class ViewController: UIViewController { 

    @IBOutlet weak var mapView: MKMapView! 
    @IBOutlet weak var slidingView: UIView! 
    @IBOutlet weak var slidingViewHeight: NSLayoutConstraint! 
    var maxMetersDistance:CGFloat = 10000.0; // customize this to set how far the map zooms out of the interest area 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     let pan = UIPanGestureRecognizer(target: self, action: "viewDidPan:") 
     self.slidingView.addGestureRecognizer(pan) 
     firstTimeCenter() 
    } 

    func firstTimeCenter(){ 
     var coordinate = CLLocationCoordinate2D(latitude: 48.8582, longitude: 2.2945) 
     let region = MKCoordinateRegionMakeWithDistance(coordinate, Double(maxMetersDistance), Double(maxMetersDistance)) 
     self.mapView.setRegion(region, animated: true) 
    } 

    func reloadMap() { 
     let height = CGFloat(self.slidingViewHeight.constant) 
     var regionDistance = (maxMetersDistance/self.view.frame.height) * height 
     regionDistance = maxMetersDistance - regionDistance 
     var coordinate = CLLocationCoordinate2D(latitude: 48.8582, longitude: 2.2945) 
     var mapRect = mapView.visibleMapRect; 
     var metersPerMapPoint = MKMetersPerMapPointAtLatitude(coordinate.latitude); 
     var metersPerPixel = CGFloat(metersPerMapPoint) * CGFloat(mapRect.size.width)/CGFloat(mapView.bounds.size.width); 
     var totalMeters = Double(metersPerPixel) * Double(height/2) 

     coordinate = self.translateCoord(coordinate, MetersLat: -totalMeters, MetersLong: 0.0) 

     let region = MKCoordinateRegionMakeWithDistance(coordinate, Double(regionDistance), Double(regionDistance)) 
     self.mapView.setRegion(region, animated: false) 
    } 

    func viewDidPan(panGesture: UIPanGestureRecognizer) { 
     let location = panGesture.locationInView(self.view) 
     self.slidingViewHeight.constant = self.view.frame.size.height - location.y 
     self.reloadMap() 
    } 

    func translateCoord(coord:CLLocationCoordinate2D, MetersLat:Double, MetersLong:Double)->CLLocationCoordinate2D{ 
     var tempCoord = CLLocationCoordinate2D() 
     var tempRegion = MKCoordinateRegionMakeWithDistance(coord, MetersLat, MetersLong); 
     var tempSpan = tempRegion.span; 
     tempCoord.latitude = coord.latitude + tempSpan.latitudeDelta; 
     tempCoord.longitude = coord.longitude + tempSpan.longitudeDelta; 
     return tempCoord; 
    } 

} 
+0

Спасибо, Хуан и Кейт! В решении Хуана есть определенная настойчивость, которую я должен выяснить, но это очень близко к тому, что я искал :) – Aodh