iOS 关键帧动画 详解

来源:互联网 发布:学java好还是c 好 编辑:程序博客网 时间:2024/05/22 16:51

https://segmentfault.com/a/1190000002411296

iOS的各种动画相漂亮,相信这是吸引很多人买iPhone的原因之一。不仅如此,这还是吸引我做iOS开发的一大原因,因为在iOS上给界面实现一些像样的动画实在是太轻松了!

这里就介绍一下iOS的block-based animation的简单用法。文后有一个坑爹问题的临时解决方法,请知情人不吝赐教。

首先是实现下面的动画:

let mView = view.viewWithTag(1) as UIView!mView.alpha = 0UIView.animateWithDuration(1, animations: {        mView.alpha = 1    }, completion: {        finished in        UIView.animateWithDuration(1, animations: {            mView.alpha = 0        })    })

新建一个 singleView 模版,在 storyboard 里加入一个 View ,颜色随便设, tag 设置成1.

然后把上文代码粘贴进 view controller 的 viewDidLoad 方法中,运行即可。

block-base 动画的用法非常简单,先设置初始状态,再在animationWithDuration 或其他动画方法的 animations 里设置结束的状态,其他的全部不用管。

上文代码中,首先让 mView 的透明度从0动画到1,然后在 completion 的 closure 中再次设置一个动画,让 mView 的透明度回到0。

View的许多属性都可以用这种方式进行动画,文档中有详细列表。

关键帧动画

UIView.animateKeyframesWithDuration(2.0,                                    // 持续时间                             delay: 0,                           options: UIViewKeyframeAnimationOptions.Repeat,  // 设置重复播放                        animations: {    // 第一个关键帧,alpha从0到1    UIView.addKeyframeWithRelativeStartTime(0,   // 开始时间                          relativeDuration: 0.5, // 持续时间                                animations: {          mView.alpha = 1    })    // 第二个关键帧,alpha从1到0    UIView.addKeyframeWithRelativeStartTime(0.5,                          relativeDuration: 0.5,                                animations: {        mView.alpha = 0    })}, completion: nil)

还是实现上面一样的动画,但这次的方式相对要更加好一些。(针对这个例子其实我更喜欢前一段代码。。。)

需要注意的一点是addKeyframeWithRelativeStartTime中的startTime和relativeDuration都是相对与整个关键帧动画的持续时间(这里是2秒)的百分比,设置成0.5就代表2*0.5=1(秒)。

坑爹货

在实现上面的效果的时候遇到了一个问题:iOS这些动画默认的变化速度是开始结束慢,中间快,于是这种循环动画的效果就不均匀。临时解决办法如下:

// 不知道Apple建不建议把 UIViewAnimationOption 用在这里,但这两行确实解决了问题。let raw = UIViewKeyframeAnimationOptions.Repeat.rawValue | UIViewAnimationOptions.CurveLinear.rawValuelet options = UIViewKeyframeAnimationOptions(raw)UIView.animateKeyframesWithDuration(2.0, delay: 0, options: options, animations: {    UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0.25, animations: {        mView.alpha = 1        mView1.alpha = 0        mView2.alpha = 1        mView3.alpha = 1    })    UIView.addKeyframeWithRelativeStartTime(0.25, relativeDuration: 0.25, animations: {        mView.alpha = 1        mView1.alpha = 1        mView2.alpha = 0        mView3.alpha = 1    })    UIView.addKeyframeWithRelativeStartTime(0.5, relativeDuration: 0.25, animations: {        mView.alpha = 1        mView1.alpha = 1        mView2.alpha = 1        mView3.alpha = 0    })    UIView.addKeyframeWithRelativeStartTime(0.75, relativeDuration: 0.25, animations: {        mView.alpha = 0        mView1.alpha = 1        mView2.alpha = 1        mView3.alpha = 1    })}, completion: nil)

原来以为关键帧动画的参数 UIViewKeyframeAnimationOptions.CalculationModeLinear 可以解决这个问题,但好像理解错了,文档里也没有提到别的办法。折腾半天快放弃的时候,误打误撞用了UIViewAnimationOptions.CurveLinear,居然解决了。又回头翻文档,确认了文档真的没有写。。。呵呵(有人找到请告诉我。。。)

使用 coreAnimation 来实现:

#pragma mark 关键帧动画-(void)translationAnimation{    //1.创建关键帧动画并设置动画属性    CAKeyframeAnimation *keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];        //2.设置关键帧,这里有四个关键帧    NSValue *key1=[NSValue valueWithCGPoint:_layer.position];//对于关键帧动画初始值不能省略    NSValue *key2=[NSValue valueWithCGPoint:CGPointMake(80, 220)];    NSValue *key3=[NSValue valueWithCGPoint:CGPointMake(45, 300)];    NSValue *key4=[NSValue valueWithCGPoint:CGPointMake(55, 400)];    NSArray *values=@[key1,key2,key3,key4];    keyframeAnimation.values=values;    //设置其他属性    keyframeAnimation.duration=8.0;    keyframeAnimation.beginTime=CACurrentMediaTime()+2;//设置延迟2秒执行            //3.添加动画到图层,添加动画后就会执行动画    [_layer addAnimation:keyframeAnimation forKey:@"KCKeyframeAnimation_Position"];}
#pragma mark 关键帧动画-(void)translationAnimation{    //1.创建关键帧动画并设置动画属性    CAKeyframeAnimation *keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];        //2.设置路径    //绘制贝塞尔曲线    CGPathRef path=CGPathCreateMutable();    CGPathMoveToPoint(path, NULL, _layer.position.x, _layer.position.y);//移动到起始点    CGPathAddCurveToPoint(path, NULL, 160, 280, -30, 300, 55, 400);//绘制二次贝塞尔曲线    keyframeAnimation.path=path;//设置path属性    CGPathRelease(path);//释放路径对象    //设置其他属性    keyframeAnimation.duration=8.0;    keyframeAnimation.beginTime=CACurrentMediaTime()+5;//设置延迟2秒执行            //3.添加动画到图层,添加动画后就会执行动画    [_layer addAnimation:keyframeAnimation forKey:@"KCKeyframeAnimation_Position"];}
#pragma mark 关键帧移动动画-(CAKeyframeAnimation *)translationAnimation{    CAKeyframeAnimation *keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];        CGPoint endPoint= CGPointMake(55, 400);    CGPathRef path=CGPathCreateMutable();    CGPathMoveToPoint(path, NULL, _layer.position.x, _layer.position.y);    CGPathAddCurveToPoint(path, NULL, 160, 280, -30, 300, endPoint.x, endPoint.y);        keyframeAnimation.path=path;    CGPathRelease(path);    [keyframeAnimation setValue:[NSValue valueWithCGPoint:endPoint] forKey:@"KCKeyframeAnimationProperty_EndPosition"];        return keyframeAnimation;}


0 0
原创粉丝点击