CAKeyFrameAnimation绘制沿轨迹移动核心动画

2017-04-20  本文已影响0人  金丝楠

KeyFrameAnimation来源于动画产业,最早做动画片的时候,会分为几个角色,牛点的人会根据剧情等因素把场景中的关键画面画出来,剩下的不那么牛的人则根据这些关键画面把一些过渡性的图片补足,假设一秒需要20张图片,关键图片可能有5张,剩下的15张则根据这5张的内容来补齐,这就是最早的key frame的来源。其实在视频编解码中也经常会碰到类似的属于,比如KeyFrame和I帧P帧这些名词,都是跟这些有关的。

在iOS中,如果你使用CAKeyFrameAnimation,则需要提供一些关键点,然后iOS在显示的过程中会根据这些信息自动补齐过渡性的内容。

我们可以用下面一个飞机飞行线路的例子来说明

- (void)drawSpaceCurve
{
    // Create a path
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [bezierPath moveToPoint:CGPointMake(0, 150)];
    [bezierPath addCurveToPoint:CGPointMake(300, 150)
                  controlPoint1:CGPointMake(75, 0)
                  controlPoint2:CGPointMake(225, 300)];

    // Draw the path using CAShapeLayer
    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.path = bezierPath.CGPath;
    pathLayer.fillColor = [UIColor clearColor].CGColor;
    pathLayer.strokeColor = [UIColor redColor].CGColor;
    pathLayer.lineWidth = 3.0f;
    [self.view.layer addSublayer:pathLayer];

    // Add the ship
    CALayer *shipLayer = [CALayer layer];
    shipLayer.frame = CGRectMake(0, 0, 64, 64);
    shipLayer.position = CGPointMake(0, 150);
    shipLayer.contents = (__bridge id)[UIImage imageNamed:@"Ship"].CGImage;
    [self.view.layer addSublayer:shipLayer];

    // Create the keyframe animation
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position";
    animation.duration = 4.0f;
    animation.path = bezierPath.CGPath;
    [shipLayer addAnimation:animation forKey:nil];
}
轨迹动画1.png

在代码运行中,我们确实看到了飞机的运行轨迹和我们定义的bezierPath一致,但有个问题,就是飞机的机头方向没有在运行过程中做调整,这便使动画看起来怪怪的,不过好在Apple已经预见到这个需求,所以在CAKeyFrameAnimation中提供了一个名为rotationMode的属性,当我们把这个属性设置为kCAAnimationRotateAuto时,飞机在运行过程中机头始终超前,实现了我们的需求。

animation.rotationMode = kCAAnimationRotateAuto;

另外在实际的动画应用中,我们经常会使用到多个动画效果一同展示的情况,这种情况我们可以通过CAAnimationGroup来实现,它的用法和单独设置一个动画的效果没有太大的区别,但当你把多种效果组合到一起,在展示的时候,就可以轻松完成多个效果的同时展示。

我们还是用上面的轨迹来演示,不过把飞机换成了一个色块,动画是使色块不但按照我们规定好的路径运动,并且在运动中进行颜色的变换。

- (void)testAnimationGroup
{
    UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
    [bezierPath moveToPoint:CGPointMake(0, 150)];
    [bezierPath addCurveToPoint:CGPointMake(300, 150)
                  controlPoint1:CGPointMake(75, 0)
                  controlPoint2:CGPointMake(225, 300)];

    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.path = bezierPath.CGPath;
    pathLayer.fillColor = [UIColor clearColor].CGColor;
    pathLayer.strokeColor = [UIColor redColor].CGColor;
    pathLayer.lineWidth = 3.0f;
    [self.view.layer addSublayer:pathLayer];

    CALayer *colorLayer = [CALayer layer];
    colorLayer.frame = CGRectMake(0, 0, 64, 64);
    colorLayer.position = CGPointMake(0, 150);
    colorLayer.backgroundColor = [UIColor greenColor].CGColor;
    [self.view.layer addSublayer:colorLayer];

    CAKeyframeAnimation *animation1 = [CAKeyframeAnimation animation];
    animation1.keyPath = @"position";
    animation1.path = bezierPath.CGPath;
    animation1.rotationMode = kCAAnimationRotateAuto;

    CABasicAnimation *animation2 = [CABasicAnimation animation];
    animation2.keyPath = @"backgroundColor";
    animation2.toValue = (__bridge id)[UIColor redColor].CGColor;

    CAAnimationGroup *group = [CAAnimationGroup animation];
    group.animations = @[animation1, animation2];
    group.duration = 4.0f;

    [colorLayer addAnimation:group forKey:nil];
}
轨迹动画2.png
上一篇 下一篇

猜你喜欢

热点阅读