Core Animation: Animations not smooth and judders/shudders - Help required

Discussion in 'iOS Programming' started by mja786, May 9, 2012.

  1. mja786, May 9, 2012
    Last edited by a moderator: May 9, 2012

    mja786 macrumors newbie

    Joined:
    Feb 21, 2012
    #1
    I am new to IOS development, and will be grateful for any help.

    I'm currently working with Core Animation. I have noticed that when I have several animations (either CABasicAnimation or CAKeyFrameAnimation) animating at the same time they judder and the layers become blurry. The more animations there are, animating simultaneously, the worse this problem is. Everything works fine in the IOS simulator on an iMac, the problem occurs when I test it on an iPhone.

    I am using CALayer to create many layers then adding animations to those layers.

    Here is a snippet of the code:

    Code:
    - (void) doAnimation
    {
        
        // Rotate shape about z axis
        CABasicAnimation *rotation;
        rotation = [CABasicAnimation    animationWithKeyPath:@"transform.rotation.z"];
        rotation.duration = 10.0;
        rotation.beginTime = CACurrentMediaTime();
        [rotation setToValue:[NSNumber numberWithFloat:32]];
       
       
    
        //Blue Square
        CALayer *squareLayer = [CALayer layer];
        squareLayer.backgroundColor = [UIColor blueColor].CGColor;
        squareLayer.shadowOffset = CGSizeMake(0, 3);
        squareLayer.shadowRadius = 5.0;
        squareLayer.shadowColor = [UIColor blackColor].CGColor;
        squareLayer.shadowOpacity = 0.8;
        squareLayer.frame = CGRectMake(-70, 50, 50, 50);
        
    
        // Move Blue Square
        CABasicAnimation *animation1;
        animation1 = [CABasicAnimation animationWithKeyPath:@"position"];
        
        animation1.fromValue = [NSValue valueWithCGPoint:CGPointMake(-80, 50)];
        animation1.toValue = [NSValue valueWithCGPoint:CGPointMake(400, 50)];
        animation1.duration = 4.0;
        animation1.beginTime = CACurrentMediaTime();
        
        //Add squareLayer to the view   
        [self.view.layer addSublayer:squareLayer];
    
        //Add animations to squareLayer 
        [squareLayer addAnimation:rotation forKey:@"transform"];
        [squareLayer addAnimation:animation1 forKey:@"position"];
    
         
    
        //Create a UIBezierPath for a Triangle
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(200,200), NO, 0);   
        
        UIBezierPath *trianglePath = [UIBezierPath bezierPath];
        
        [trianglePath moveToPoint:CGPointMake(100, 25)];
        [trianglePath addLineToPoint:CGPointMake(165, 137.58)];
        [trianglePath addLineToPoint:CGPointMake(35, 137.58)];
        [trianglePath closePath];
        
        //Fill the UIBezierPath with a color 
        [[UIColor magentaColor]setFill];
        [trianglePath fill];
        
        //Create a UIImage using the current context. 
        UIImage *triangle = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        //Create a layer for triangle, use the UIImage triangle 
        CALayer *triangleLayer = [CALayer layer];
        triangleLayer.frame = CGRectMake(-100, 150, 100, 100);
        triangleLayer.contents = (id)triangle.CGImage;
    
        triangleLayer.shadowOffset = CGSizeMake(0,3);
        triangleLayer.shadowRadius = 5.0;
        triangleLayer.shadowColor = [UIColor blackColor].CGColor;
        triangleLayer.shadowOpacity = 0.8;
            
        //Move Triangle Animation
        CABasicAnimation *animation2;
        animation2 = [CABasicAnimation animationWithKeyPath:@"position"];
        animation2.fromValue = [NSValue valueWithCGPoint:CGPointMake(-100, 150)];
        animation2.toValue = [NSValue valueWithCGPoint:CGPointMake(400, 150)];
        animation2.duration = 4.0;
        animation2.beginTime = CACurrentMediaTime();
      
        //Add triangleLayer to the view  
        [self.view.layer addSublayer:triangleLayer];
        
        //Add animations to triangleLayer
        [triangleLayer addAnimation:rotation forKey:@"transform"];
        [triangleLayer addAnimation:animation2 forKey:@"position"];
    
    }
    As you can see, there is a squareLayer and a triangleLayer to which I add animations. If I set the animations to animate one after the other i.e.
    animation2.begintime = CACurrentMediaTime() + 5.0; the animations are very smooth - but if the animations remain as they are coded above (animating simultaneously), they are no longer smooth - and judder. As I said, the problem is on the iPhone itself not on the IOS simulator on a Mac. It gets worse as I add more animations to the doAnimation method.

    Any advice will be appreciated.
     
  2. CodeBreaker, May 9, 2012
    Last edited: May 9, 2012

    CodeBreaker macrumors 6502

    Joined:
    Nov 5, 2010
    Location:
    Sea of Tranquility
    #2
    First, all apps will be a lot smoother on the iOS Simulator as compared to the actual device. This is because it is a _simulator_, which executes iOS code on your Mac using your Mac's CPU, which is at least 10 X more powerful than your iPhone's CPU.

    What you can do is use Instruments and get a CPU/OpenGL profile of your App. Then looking at the trace, you can identify which parts of the animation are more taxing to the CPU/GPU. Then you can arrange your animations accordingly.

    Also, it is generally much faster to animate rasterized layers. So after drawing a shape (layer), you should rasterize a layer, like such:

    Code:
    [self.someComplexShapeLayer setShouldRasterize:YES]
     
     

Share This Page