25

I made one demo project (from Moving-MKAnnotationView demo on github) for moving car on map following is its link

https://github.com/pratikbhiyani/Moving-MKAnnotationView

I edit my code on the basis of given answer by vinaut but still problem is that when we zoom or scroll the map animation get distract in ios 7 and in ios 6 when we zoom or scroll the map annotation set to its original angle for a while.

Below is a screen shot of my Demo Project

enter image description here

Here is some code i change

- (void) setPosition : (id) posValue;
{
    NSLog(@"set position");

    //extract the mapPoint from this dummy (wrapper) CGPoint struct
    MKMapPoint mapPoint = *(MKMapPoint*)[(NSValue*)posValue pointerValue];

    CLLocationCoordinate2D coord = MKCoordinateForMapPoint(mapPoint);
    CGPoint toPos;
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {

        toPos = [self.mapView convertCoordinate:coord toPointToView:self.mapView];
    }
    else
    {
        CGFloat zoomFactor =  self.mapView.visibleMapRect.size.width / self.mapView.bounds.size.width;
        toPos.x = mapPoint.x/zoomFactor;
        toPos.y = mapPoint.y/zoomFactor;
    }



    [self setTransform:CGAffineTransformMakeRotation([self getHeadingForDirectionFromCoordinate:MKCoordinateForMapPoint(previousPoint) toCoordinate: MKCoordinateForMapPoint(mapPoint)])];

    if (MKMapRectContainsPoint(self.mapView.visibleMapRect, mapPoint)) {

        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];

        animation.fromValue = [NSValue valueWithCGPoint:self.center];
        animation.toValue = [NSValue valueWithCGPoint:toPos];
        animation.duration = 1.0;
        animation.delegate = self;
        animation.fillMode = kCAFillModeForwards;
        //[self.layer removeAllAnimations];
        [self.layer addAnimation:animation forKey:POSITIONKEY];

        //NSLog(@"setPosition ANIMATED %x from (%f, %f) to (%f, %f)", self, self.center.x, self.center.y, toPos.x, toPos.y);
    }

    self.center = toPos;

    previousPoint = mapPoint;
}

My goal is to move car same like in uber app.

Pratik B
  • 1,599
  • 1
  • 15
  • 32

3 Answers3

14

It seems that something changed with the conversion functions for CLCoordinate2D/MKMapPoint/CGPoint...

Detecting a point in a MKPolygon broke with iOS7 (CGPathContainsPoint)

The annotation disappears because the conversion beetween MkMapPoints and CGIPoints does not work anymore, if you log the "position" of the CALayer you will get points way outside the view. No idea why it works when doing touch events.

If you change the function to :

    - (void) setPosition : (id) posValue; 
{
    //extract the mapPoint from this dummy (wrapper) CGPoint struct
    MKMapPoint mapPoint = *(MKMapPoint*)[(NSValue*)posValue pointerValue];  
    CLLocationCoordinate2D coord = MKCoordinateForMapPoint(mapPoint);

    CGPoint toPos = [self.mapView convertCoordinate:coord toPointToView:self.mapView];


    if (MKMapRectContainsPoint(self.mapView.visibleMapRect, mapPoint)) {

        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];

        animation.fromValue = [NSValue valueWithCGPoint:self.center];
        animation.toValue = [NSValue valueWithCGPoint:toPos];   
        animation.duration = 0.8;
        animation.delegate = self;
        animation.fillMode = kCAFillModeForwards;
        //[self.layer removeAllAnimations];
        [self.layer addAnimation:animation forKey:POSITIONKEY];

        //NSLog(@"setPosition ANIMATED %x from (%f, %f) to (%f, %f)", self, self.center.x, self.center.y, toPos.x, toPos.y);
    }   

    self.center = toPos;


}

It should be working again.

Community
  • 1
  • 1
vinaut
  • 2,416
  • 15
  • 13
  • hey thanks for answer but the problem with your code is the annotation distract from the path when map move. – Pratik B Oct 12 '13 at 09:12
  • I don't know how it was supposed to behave in iOS 6. I pointed out the reason why the annotation it was not showing, you should be able to modify the code as you see fit knowing that. For example, if you don't want the annotation to update when panning or zooming, just have a property keeping track of the current mapView.visibleRect and compare it to the new value in setPosition, and do not run the animation if it has changed. Give it a shot and let me know if you succeed. – vinaut Oct 12 '13 at 10:32
  • In ios 6 its not distract from path when panning or zooming. and I can't stop animation. it is responsible for smooth driving. – Pratik B Oct 12 '13 at 10:54
  • 3
    hey friend , You are close to answer so +50 for you :) – Pratik B Oct 18 '13 at 14:08
  • Hey sorry for unaccept your answer but i will accept the answer after the completion of bounty. – Pratik B Oct 22 '13 at 11:16
14

I'm the original contributor to Moving-MKAnnotationView (https://github.com/100grams/Moving-MKAnnotationView.git). This component was originally written using iOS4.3 and a lot has changed since. :-)

The root cause here was the conversion from MKMapPoint to CGPoint (screen coordinates). Although the code worked before, it breaks on iOS7 and I fixed it by using this to convert the lat/lon coordinate to screen coordinates:

convertCoordinate:toPointToView:

I've committed this fix, with a few other updates, to https://github.com/100grams/Moving-MKAnnotationView.git so it now works on iOS7/Xcode5.

100grams
  • 3,502
  • 3
  • 30
  • 27
  • thanks for reply. its very nice demo.but problem is when theGroup.duration = 0.2 and when i increase duration to 1.0 for smooth animation , annotation distract from path on scalling or zooming the map. – Pratik B Oct 22 '13 at 17:00
  • Yes that is indeed a caveat. I guess you should abort/stop any animation while the map is being panned/zoomed to avoid this side effect. – 100grams Dec 17 '13 at 17:54
  • Yes I tried it with remove animation but Unfortunately it shows same distraction :( – Pratik B Dec 17 '13 at 18:01
  • 1
    Did you try to hide the moving annotations, i.e. set alpha=0 while map is panning/zooming? – 100grams Dec 18 '13 at 09:20
  • I want to add cars on the map and show their movement but the problem is that I am getting the position of cars from an api.So I want to animate cars through the latitude and longitude that I am getting from that api.How can I achieve that?Any help will be much appreciated. – Waqar Khalid Mar 22 '17 at 08:19
  • https://github.com/100grams/Moving-MKAnnotationView.git nice demo but can you give idea to move pin using lat long which i get from api instand of pre define coordinates? for swift – Nipul Daki Oct 04 '17 at 13:29
1

The problem of distracting a car while zoom/scrolling the map. Actually it can not be achieved by adding an animation to annotation. I have found out the Interpolate function through which I can get the locations between "From" and "To" coordinates and set it to the annotation(setting annotation coordinate in milliseconds) will look like an animation.

It is not an issue of iOS or Map, if you are adding animation to annotation it will add to annotation layer not respect to the map point.