Map camera position changes sharply without animation

15,941

Solution 1

I think the problem with this is that calling setCamera will snap to the new zoom level without animating - and so the following call to animateToCameraPosition won't actually animate anything, as the camera is already at that position.

However, if you removed the call to setCamera then you'd probably end up in an infinite loop, as the call to animateToCameraPosition won't actually update the camera until some time later (as the animation plays), and so on the next iteration of the loop the markers would still all be visible.

What you need to do is calculate the final zoom level that you need, and then make a single call to animateToCameraPosition to move the camera there.

I posted some code for calculating the centre and zoom level for a camera to fit a bounds here:

How to setRegion with google maps sdk for iOS?

So you could use something similar to calculate a camera position which would fit your markers to the screen.

Solution 2

Much simpler answer:

Instead of

[self.mapView setCamera:[GMSCameraPosition cameraWithTarget:self.mapView.camera.target zoom:zoom]];
[self.mapView animateToCameraPosition:[GMSCameraPosition cameraWithTarget:self.mapView.camera.targetAsCoordinate zoom:zoom]];

Do this:

[self.mapView animateToCameraPosition:[GMSCameraPosition cameraWithTarget:[GMSCameraPosition cameraWithTarget:self.mapView.camera.target zoom:zoom]]];

Works for me!

Solution 3

GMSCameraPosition *newCameraPosition = [GMSCameraPosition cameraWithTarget:cordinate zoom:position.zoom];
dispatch_async(dispatch_get_main_queue(), ^{
        [self.mapView animateToCameraPosition:newCameraPosition];
 });

Solution 4

This code performs smooth/animated repositioning of mapview's camera to the selected marker.

- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {

     [mapView animateWithCameraUpdate:[GMSCameraUpdate setTarget:marker.position]];
     mapView.selectedMarker = marker;
     return YES;
}
Share:
15,941
Geek
Author by

Geek

iOS, Android

Updated on June 23, 2022

Comments

  • Geek
    Geek almost 2 years

    I use google Maps SDK for iOS. I have markers on my map and want to set proper zoom so that markers are separate and also markers should be visible on screen all at once. I am able to do it.I have done using logic that if all markers are visible then zoom in. But the problem is that map camera is changing sharply. I tried a lot to animate this zoom but I failed to do to. I tried animateToCameraPosition, animateToZoom and UIView animation method.

    - (BOOL)allCoordinatesVisibleWithLatitudes:(NSArray *)arrayOfLatitudes Longitudes:(NSArray *)arrayOfLongitudes
        {
        CLLocationCoordinate2D coordinate;
        for(int i=0;i<arrayOfLatitudes.count;i++)
        {
            coordinate = CLLocationCoordinate2DMake([[arrayOfLatitudes objectAtIndex:i] floatValue], [[arrayOfLongitudes objectAtIndex:i] floatValue]);
            if(![self.mapView.projection containsCoordinate:coordinate])
            {
                return NO;
            }
        }
        return YES;
    }
    
    
    - (void)setZoomToHaveProperView
    {
        NSMutableArray * arrayOfLatitudes = [[NSMutableArray alloc] init];
        NSMutableArray * arrayOfLongitudes = [[NSMutableArray alloc] init];
        RS_SingleMatch * singleMatch = [[RS_SingleMatch alloc] init];
        float zoom = 0.0;
    
        // You may ignore this first for loop. it just takes coordinate of all markers in     arrays.
    
        for(int i=0;i<=self.userMatches.arrayOfMatches.count;i++)
        {
            if(i==self.userMatches.arrayOfMatches.count)
            {
                RS_Trip * userTrip = [[RS_Trip alloc] init];
                [arrayOfLatitudes addObject:[NSNumber numberWithFloat:userTrip.fromLat]];
                [arrayOfLongitudes addObject:[NSNumber numberWithFloat:userTrip.fromLon]];
                if(self.segmentedControl.selectedSegmentIndex == 1)
                {
                    [arrayOfLatitudes addObject:[NSNumber numberWithFloat:userTrip.toLat]];
                    [arrayOfLongitudes addObject:[NSNumber numberWithFloat:userTrip.toLon]];
                }
            }
            else
            {
                singleMatch = [self.userMatches.arrayOfMatches objectAtIndex:i];
                [arrayOfLatitudes addObject:[NSNumber numberWithFloat:singleMatch.fromLat]];
                [arrayOfLongitudes addObject:[NSNumber numberWithFloat:singleMatch.fromLong]];
                if(self.segmentedControl.selectedSegmentIndex == 1)
                {
                    [arrayOfLatitudes addObject:[NSNumber numberWithFloat:singleMatch.toLat]];
                    [arrayOfLongitudes addObject:[NSNumber numberWithFloat:singleMatch.toLong]];
                }
            }
    }
        zoom = self.mapView.camera.zoom;
    
        // if all coordinates are visible then zoom in
        if([self allCoordinatesVisibleWithLatitudes:arrayOfLatitudes Longitudes:arrayOfLongitudes])
        {
            while ([self allCoordinatesVisibleWithLatitudes:arrayOfLatitudes Longitudes:arrayOfLongitudes])
            {
                zoom += 0.5;
                [self.mapView setCamera:[GMSCameraPosition cameraWithTarget:self.mapView.camera.target zoom:zoom]];
                [self.mapView animateToCameraPosition:[GMSCameraPosition cameraWithTarget:self.mapView.camera.targetAsCoordinate zoom:zoom]];
            }
        }
    }
    

    I also tried reversing order of setting mapview camera and animating camera in while loop of if condition. I spent 3 days just doing it. Now asking for your help. Thank you in advance.

  • Geek
    Geek about 11 years
    Thanks for the formula. This is what I needed.
  • rducom
    rducom over 9 years
    Maybe you can give more details about your answer and explain what your code intend to do.