Плавная прокрутка в Google Maps SDK для iOS - программирование

Плавная прокрутка в Google Maps SDK для iOS

Поэтому я хочу ограничить прокручиваемую область Google Maps определенным прямоугольником на карте, основанным на значениях широты и долготы. Для этого я написал следующий код:

-(void) viewDidLoad{
    startLat = 43.331635f;
    startLong = -74.472913f;
    endLat = 43.329106f;
    endLong = -74.470589f;
    float cameraPosLat = (startLat + endLat) / 2.0f;
    float cameraPosLong = (startLong + endLong) / 2.0f;

    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:cameraPosLat
                                                        longitude:cameraPosLong
                                                             zoom:18];
    mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
    mapView.mapType = kGMSTypeSatellite;
    mapView.delegate = self;
    mapView.myLocationEnabled = YES;
    [mapView setMinZoom:18 maxZoom:mapView.maxZoom];
    self.view = mapView;
    marker.map = mapView;
}

-(void) mapView:(GMSMapView *)delegateMapView didChangeCameraPosition:(GMSCameraPosition *)position{
    if(delegateMapView.camera.target.latitude > startLat){
        [delegateMapView moveCamera:[GMSCameraUpdate setTarget:CLLocationCoordinate2DMake(startLat, delegateMapView.camera.target.longitude)]];
    }
    if(delegateMapView.camera.target.latitude < endLat){
        [delegateMapView moveCamera:[GMSCameraUpdate setTarget:CLLocationCoordinate2DMake(endLat, delegateMapView.camera.target.longitude)]];
    }
    if(delegateMapView.camera.target.longitude < startLong){
        [delegateMapView moveCamera:[GMSCameraUpdate setTarget:CLLocationCoordinate2DMake(delegateMapView.camera.target.latitude, startLong)]];
    }
    if(delegateMapView.camera.target.longitude > endLong){
        [delegateMapView moveCamera:[GMSCameraUpdate setTarget:CLLocationCoordinate2DMake(delegateMapView.camera.target.latitude, endLong)]];
    }
}

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

Любая помощь будет принята с благодарностью, спасибо!

4b9b3361

Ответ 1

Попробуйте это вместо:

-(void) mapView:(GMSMapView *)delegateMapView didChangeCameraPosition:(GMSCameraPosition *)position{
    if(delegateMapView.camera.target.latitude > startLat){
        [delegateMapView animateToCameraPosition:[GMSCameraPosition 
           cameraWithLatitude:startLat 
           longitude:delegateMapView.camera.target.longitude
           zoom:delegateMapView.camera.zoom]];
    }
    if(delegateMapView.camera.target.latitude < endLat){
        [delegateMapView animateToCameraPosition:[GMSCameraPosition 
           cameraWithLatitude:endLat 
           longitude:delegateMapView.camera.target.longitude
           zoom:delegateMapView.camera.zoom]];
    }
    if(delegateMapView.camera.target.longitude < startLong){
        [delegateMapView animateToCameraPosition:[GMSCameraPosition 
           cameraWithLatitude:delegateMapView.camera.target.latitude 
           longitude:startLong
           zoom:delegateMapView.camera.zoom]];
    }
    if(delegateMapView.camera.target.longitude > endLong){
        [delegateMapView animateToCameraPosition:[GMSCameraPosition 
           cameraWithLatitude:delegateMapView.camera.target.latitude 
           longitude:endLong
           zoom:delegateMapView.camera.zoom]];
    }
}

Ответ 2

Соответственно API docs

-[GMSMapView moveCamera:]

Восстанавливает камеру в соответствии с инструкциями, указанными в обновлении. Перемещение происходит мгновенно, а последующее getCameraPosition() будет отражать новую позицию. См. CameraUpdateFactory для набора обновлений.

Итак, если вы хотите анимацию, вам нужно использовать

-[GMSMapView animateCamera:]

Помните, что ваш делегат будет вызываться несколько раз во время анимации.

Ответ 3

Неточность float может быть частью вашей проблемы, вызывающей многократные вызовы делегатов. Я бы использовал NSNumber для хранения вашего min/max и выполнения более низких/больших проверок. Я бы использовал флаг, чтобы делегат не выполнял дважды.

Что-то в этом роде:

NSNumber *lat = [NSNumber numberWithDouble:delegateMapView.camera.target.latitude];
if(lat > self.startLat && !self.hasChangedCameraLat){
    [delegateMapView animateToCameraPosition:[GMSCameraPosition 
        cameraWithLatitude:[self.startLat doubleValue] 
        longitude:delegateMapView.camera.target.longitude
        zoom:delegateMapView.camera.zoom]];
    self.hasChangedCameraLat = YES;
}
else {
    self.hasChangedCameraLat = NO;
}