yandex / mapkit-ios-demo

MapKit iOS demo
Other
84 stars 27 forks source link

Как работает focusRect? #155

Closed user1231232131 closed 2 years ago

user1231232131 commented 2 years ago

Можно ли менять значение focusRect/focusPoint во время работы карты? На экране предусмотрено 2 состояния: карта в полный экран и карта, перекрытая боттомШит снизу до половины. Состояния эти меняются. При попытке изменить значения focusRect/focusPoint карта дергается в область близкую к необходимой, а затем метод move подъезжает до необходимой точки с анимацией. Происходят эти дерганья рандомно, поэтому решил узнать можно ли вообще менять значения этих параметров когда карта уже находится на экране, или только при запуске один раз. В решении использовал рекомендации из https://github.com/yandex/mapkit-ios-demo/issues/127, https://github.com/yandex/mapkit-android-demo/issues/117. В целом проблем в работе focusRect после установки нет, методы move центрирую камеру в нужной области, поэтому думаю, что все остально сделано верно.

teshca commented 2 years ago

Указанные методы можно вызывать в любое время

user1231232131 commented 2 years ago

Спасибо за оперативный ответ. Накидал пример который показывает какое поведение я имею в виду. Или в примере можно исправить что-то? Запустить можно из mapkit-ios-demo поместив пример в соотвествующий класс. Или это правильное поведение?

`class MapViewController: UIViewController { @IBOutlet private weak var mapView: YMKMapView!

private let TARGET_LOCATION = YMKPoint(latitude: 59.945933, longitude: 30.320045)
private var MAP_SIZE = CGSize.zero

override func viewDidLoad() {
    super.viewDidLoad()
    mapView.mapWindow.addSizeChangedListener(with: self)
    setupGestures()
    setupPlacemark()
    moveMap()
}

@objc func centerTapped() {
    mapView.mapWindow.focusRect = .init(topLeft: .init(x: 0,
                                                       y: 0),
                                        bottomRight: .init(x: Float(MAP_SIZE.width),
                                                           y: Float(MAP_SIZE.height)))
    moveMap()
}

@objc func topTapped() {
    mapView.mapWindow.focusRect = .init(topLeft: .init(x: 0,
                                                       y: 0),
                                        bottomRight: .init(x: Float(MAP_SIZE.width),
                                                           y: Float(MAP_SIZE.height) / 2))
    moveMap()
}

private func setupPlacemark() {
    _ = mapView.mapWindow.map.mapObjects.addCircle(with: .init(center: TARGET_LOCATION,
                                                               radius: 20),
                                                   stroke: .red,
                                                   strokeWidth: 2,
                                                   fill: .blue)
}

private func setupGestures() {
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(topTapped))
    let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(centerTapped))
    doubleTapGesture.numberOfTapsRequired = 2
    tapGesture.require(toFail: doubleTapGesture)
    mapView.addGestureRecognizer(tapGesture)
    mapView.addGestureRecognizer(doubleTapGesture)
}

private func moveMap() {
    mapView.mapWindow.map.move(
        with: YMKCameraPosition(target: TARGET_LOCATION, zoom: 15, azimuth: 0, tilt: 0),
        animationType: YMKAnimation(type: YMKAnimationType.smooth, duration: 5),
        cameraCallback: nil)
}

}

extension MapViewController: YMKMapSizeChangedListener { func onMapWindowSizeChanged(with mapWindow: YMKMapWindow, newWidth: Int, newHeight: Int) { MAP_SIZE = .init(width: newWidth, height: newHeight) } } `

teshca commented 2 years ago

Не совсем понятно какого эффекта вы пытаетесь добиться вызывая mapMove после установки focusRect Изменение focusRect само по себе приведет к смещению карты в состояния где TARGET_LOCATION будет находиться в его центре.

user1231232131 commented 2 years ago

Наверно я неправильно понял суть работы focusRect. А как можно добиться, чтобы смещение при установке focusRect происходило плавно, а не просто перебрасывало? Желаемое поведение, как в Яндекс Go

teshca commented 2 years ago

Одновременно с выставлением focusRect нужно позвать move без анимации который вернет камеру на старое место, после этого запустить move с анимацией.

user1231232131 commented 2 years ago

Условно если камера до момента изменения focusRect была направлена в центр экрана, то шаги следующие:

teshca commented 2 years ago

без конвертации не обойтись

YMKPoint *target = [self.mapView.mapWindow screenToWorldWithScreenPoint:focusPoint]; YMKCameraPosition *position = self.map.cameraPosition;   self.mapView.mapWindow.focusPoint = focusPoint;   YMKCameraPosition *newPosition = [YMKCameraPosition cameraPositionWithTarget:target zoom:position.zoom azimuth:position.azimuth tilt:position.tilt]; [self.map moveWithCameraPosition:newPosition];

user1231232131 commented 2 years ago

Спасибо большое!