iosobjective-cgoogle-mapsgoogle-maps-markerspulse

Pulse ring animation around a Google Maps marker iOS


I want to add a pulse ring animation around a marker as a current user location in iOS google maps (like Uber). I tried with adding CABasicAnimation to marker layer by addAnimation. It is not working.

Also I tried animate the scale of the marker but the scale change did not happen. Can anybody help me with this thing?


Solution

  • somehow it is working now. I created a custom view and set that view into GMSMarker iconView. After that added animation into view layer.

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(200, 200, 100, 100)];
    view.backgroundColor = [UIColor redColor];
    view.layer.cornerRadius = 50;
    
    GMSMarker *m = [GMSMarker markerWithPosition:mapView_.myLocation.coordinate];
    m.iconView = view;
    m.map = mapView_;
    
    
    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    scaleAnimation.duration = 1.5;
    scaleAnimation.repeatCount = HUGE_VAL;
    scaleAnimation.autoreverses = YES;
    scaleAnimation.fromValue = [NSNumber numberWithFloat:0.1];
    scaleAnimation.toValue = [NSNumber numberWithFloat:1.2];
    
    [view.layer addAnimation:scaleAnimation forKey:@"scale"];
    

    Another method:


    GMSMarker *m = [GMSMarker markerWithPosition:mapView_.myLocation.coordinate];
    
    //custom marker image
        UIImageView *pulseRingImg = [[UIImageView alloc] initWithFrame: CGRectMake(-30, -30, 78, 78)];
        pulseRingImg.image = [UIImage imageNamed:@"Pulse"];
        pulseRingImg.userInteractionEnabled = NO;
    
    
        //transform scale animation
        CABasicAnimation *theAnimation;
        theAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.xy"];
        theAnimation.duration = 3.5;
        theAnimation.repeatCount = HUGE_VALF;
        theAnimation.autoreverses = NO;
        theAnimation.fromValue = [NSNumber numberWithFloat:0.0];
        theAnimation.toValue = [NSNumber numberWithFloat:2.0];
    
    //alpha Animation for the image
        CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
        animation.duration = 3.5;
        animation.repeatCount = HUGE_VALF;
        animation.values = [NSArray arrayWithObjects:
                           [NSNumber numberWithFloat:1.0],
                           [NSNumber numberWithFloat:0.5],
                           [NSNumber numberWithFloat:0.0], nil];
        animation.keyTimes = [NSArray arrayWithObjects:
                             [NSNumber numberWithFloat:0.0],
                             [NSNumber numberWithFloat:1.2],
                             [NSNumber numberWithFloat:3.5], nil];
        [pulseRingImg.layer addAnimation:animation forKey:@"opacity"];
    
    
        [pulseRingImg.layer addAnimation:theAnimation forKey:@"pulse"];
        pulseRingImg.userInteractionEnabled = NO;
    
        m.iconView = pulseRingImg;
        [m.layer addSublayer:pulseRingImg.layer];
        m.map = mapView_;
        m.groundAnchor = CGPointMake(0.5, 0.5);
    

    Another one:

    m = [GMSMarker markerWithPosition:mapView_.myLocation.coordinate];
    
        //custom marker image
        UIImageView *pulseRingImg = [[UIImageView alloc] initWithFrame: CGRectMake(-30, -30, 78, 78)];
        pulseRingImg.image = [UIImage imageNamed:@"Pulse"];
        pulseRingImg.userInteractionEnabled = NO;
    
        float duration = 3.5f;
    
        [CATransaction begin];
        [CATransaction setAnimationDuration: duration];
    
        //transform scale animation
        CABasicAnimation *theAnimation;
        theAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.xy"];
        theAnimation.repeatCount = HUGE_VALF;
        theAnimation.autoreverses = NO;
        theAnimation.fromValue = [NSNumber numberWithFloat:0.0];
        theAnimation.toValue = [NSNumber numberWithFloat:2.0];
    
        [pulseRingImg.layer addAnimation:theAnimation forKey:@"pulse"];
        pulseRingImg.userInteractionEnabled = NO;
    
        [CATransaction setCompletionBlock:^{
            //alpha Animation for the image
            CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
            animation.duration = duration;
            animation.repeatCount = HUGE_VALF;
            animation.values = [NSArray arrayWithObjects:
                                [NSNumber numberWithFloat:1.0],
                                [NSNumber numberWithFloat:0.0], nil];
            [m.iconView.layer addAnimation:animation forKey:@"opacity"];
        }];
    
        [CATransaction commit];
    
        m.iconView = pulseRingImg;
        [m.layer addSublayer:pulseRingImg.layer];
        m.map = mapView_;
        m.groundAnchor = CGPointMake(0.5, 0.5);
    

    Swift 3.0 code is below NOTE: Change the duration based on your requirement

               let m = GMSMarker(position: camera.target)
    
                //custom marker image
                let pulseRingImg = UIImageView(frame: CGRect(x: -30, y: -30, width: 78, height: 78))
                pulseRingImg.image = UIImage(named: "Pulse")
                pulseRingImg.isUserInteractionEnabled = false
                CATransaction.begin()
                CATransaction.setAnimationDuration(3.5)
    
                //transform scale animation
                var theAnimation: CABasicAnimation?
                theAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
                theAnimation?.repeatCount = Float.infinity
                theAnimation?.autoreverses = false
                theAnimation?.fromValue = Float(0.0)
                theAnimation?.toValue = Float(2.0)
                theAnimation?.isRemovedOnCompletion = false
    
                pulseRingImg.layer.add(theAnimation!, forKey: "pulse")
                pulseRingImg.isUserInteractionEnabled = false
                CATransaction.setCompletionBlock({() -> Void in
    
                    //alpha Animation for the image
                    let animation = CAKeyframeAnimation(keyPath: "opacity")
                    animation.duration = 3.5
                    animation.repeatCount = Float.infinity
                    animation.values = [Float(2.0), Float(0.0)]
                    m.iconView?.layer.add(animation, forKey: "opacity")
                })
    
                CATransaction.commit()
                m.iconView = pulseRingImg
                m.layer.addSublayer(pulseRingImg.layer)
                m.map = gmapView
                m.groundAnchor = CGPoint(x: 0.5, y: 0.5)
    

    pulse Image: pulse image for animation