iOS图与文iOS精品文章-转场&动画iOS学习记录

所有的动画、绘图、这里全搞定

2015-09-08  本文已影响1681人  SlimMan

看着我这标题就觉得有点狂啊,其实是本人最近工作有点闲,看了很多人写的sample,从中萃取精华,总结下,以防止自己忘记了,岂不白白浪费了这几天的努力。废话就这么多,现在开始正题:
先说说咱这篇文章会讲到什么吧,首先我会讲讲绘图,然后讲讲动画
咱们首先从绘图说起,


如你所见,这段代码的功能是画了一条红色的斜线。当然如果你想画一个矩形的话也是同样的一个道理,在上面的代码后面加上如下代码就好:

// 画一个矩形
CGRect arect = CGRectMake(200, 30, 49, 59);
// 设置填充色
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
// 填充矩形
CGContextFillRect(context, arect);
// 将举行显示出来
CGContextAddRect(context, arect);

效果的话自己去试吧,我就不上图了,另外谁能告诉我怎么把图片缩小,这太占地了。绘图就说这么多了,感觉用处不大啊,以后感觉用处大再补充吧。

下面对上面的代码进行说明:

  1. 我这里是将代码动画放在一个xib文件里面的,需要注意的是当xib文件被加载时它调用的是- (id)initWithCoder:(NSCoder *)aDecoder这个方法,而不是- (id)initWithFrame:(CGRect)frame这个方法,使用初始化的事情都应该放在这里面来进行。
  2. 在animate这个方法里面有这么两行
    expandAnimation.fillMode = kCAFillModeForwards;
    expandAnimation.removedOnCompletion = NO;
    需要注意的是这两行要同时写上动画才不会回去。
    动画执行的效果如下:

另外你可以利用CAAnimationGroup来组织来管理动画,使得几个动画连续执行,这样可以形成一系列的连贯动画效果,例如:
#import "NibView.h"

    @interface NibView()

    // 执行动画的对戏那个
    @property (nonatomic, strong) CAShapeLayer *shapLayer;

    @end

    @implementation NibView

    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect {
        // Drawing code
    }
    */

    // 画面的初始化在此方法内进行
    - (id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder];
        self.frame = [UIApplication sharedApplication].keyWindow.bounds;
        self.backgroundColor = [UIColor redColor];
        self.shapLayer.path = [self curvePath].CGPath;
        [self.layer addSublayer:_shapLayer];
        return self;
    }

    // 获得一个饱含曲线的path
    - (UIBezierPath *)curvePath {
        UIBezierPath *bpath = [UIBezierPath bezierPath];
        [bpath moveToPoint:CGPointMake(70, 150)];
        [bpath addCurveToPoint:CGPointMake(270, 150)
                 controlPoint1:CGPointMake(170, 80)
                 controlPoint2:CGPointMake(170, 200)];
        [bpath addCurveToPoint:CGPointMake(270, 400)
                 controlPoint1:CGPointMake(370, 230)
                 controlPoint2:CGPointMake(220, 350)];
        [bpath addLineToPoint:CGPointMake(70, 400)];
        [bpath closePath];
        return bpath;
    }


    // 获得一个path
    - (UIBezierPath *)rectPath {
        UIBezierPath *rectpath = [UIBezierPath bezierPath];
        [rectpath moveToPoint:CGPointMake(100.0, 150.0)];
        [rectpath addLineToPoint:CGPointMake(300, 150)];
        [rectpath addLineToPoint:CGPointMake(300, 400)];
        [rectpath addLineToPoint:CGPointMake(100, 400)];
        [rectpath closePath];
        return rectpath;
    }

    // 获得一个正方形边迹
    - (UIBezierPath *)suqarePath {
        UIBezierPath *squarPath = [UIBezierPath bezierPath];
        [squarPath moveToPoint:CGPointMake(10, 150)];
        [squarPath addLineToPoint:CGPointMake(310, 150)];
        [squarPath addLineToPoint:CGPointMake(310, 450)];
        [squarPath addLineToPoint:CGPointMake(10, 450)];
        [squarPath closePath];
        return squarPath;
    }


    // 执行动画
    - (void)animate {
        // 原始形态变成长方形
        CABasicAnimation *expandAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
        expandAnimation.fromValue = (__bridge id)(_shapLayer.path);
        expandAnimation.toValue = (__bridge id)[self rectPath].CGPath;
        expandAnimation.beginTime = 0;
        expandAnimation.duration = 0.5;
        [self.shapLayer addAnimation:expandAnimation forKey:nil];
        // 长方形变成正方形
        CABasicAnimation *expandAnimation2 = [CABasicAnimation animationWithKeyPath:@"path"];
        expandAnimation2.fromValue = (__bridge id)[self rectPath].CGPath;
        expandAnimation2.toValue = (__bridge id)[self suqarePath].CGPath;
        expandAnimation2.beginTime = expandAnimation.beginTime + expandAnimation.duration;
        expandAnimation2.duration = 0.5;
        // 正方形又回到原始形态
        CABasicAnimation *expandAnimation3 = [CABasicAnimation animationWithKeyPath:@"path"];
        expandAnimation3.fromValue = (__bridge id)[self suqarePath].CGPath;
        expandAnimation3.toValue = (__bridge id)(_shapLayer.path);
        expandAnimation3.beginTime = expandAnimation2.beginTime + expandAnimation2.duration;
        expandAnimation3.duration = 0.5;
        
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.animations = @[expandAnimation, expandAnimation2, expandAnimation3];
        group.beginTime = expandAnimation.beginTime;
        group.duration = expandAnimation3.beginTime + expandAnimation3.duration;
        group.fillMode = kCAFillModeForwards;
        group.removedOnCompletion = NO;
        group.repeatCount = 2;
        [self.shapLayer addAnimation:group forKey:nil];
        
    }

    // 加个按钮让动画可以重复进行
    - (IBAction)goAnimate:(UIButton *)sender {
        [self animate];
    }

    #pragma mark - initViews
    - (CAShapeLayer *)shapLayer {
        if (!_shapLayer) {
            _shapLayer = [[CAShapeLayer alloc] init];
            _shapLayer.frame = self.bounds;
            _shapLayer.fillColor = [UIColor greenColor].CGColor;
        }
        return _shapLayer;
    }

    @end

由于修改较大,使用干脆又重现全部贴了出来了,下面做以下说明:

  1. 首先为了代码的整齐我把initWithCoder里面的画边界部分的代码抽了出来,单独形成了一个方法
  2. 我增加了一个返回正方形的轨迹方法suqarePath
  3. 我对animate方法进行了修改,引入了CAAnimationGroup,这里仍需要注意的是fillMode和removedOnCompletion这两个熟悉,现在把他应用到动画组上。
通过动画组,我们可以形成各种细腻的动画效果,一切貌似变的明朗起来.

然后在修改goAnimate方法
- (CAShapeLayer *)shapLayer {
if (!_shapLayer) {
_shapLayer = [[CAShapeLayer alloc] init];
_shapLayer.frame = self.bounds;
_shapLayer.fillColor = [UIColor greenColor].CGColor;
}
return _shapLayer;
}

这里我们让图层旋转360度,运行效果如下:



另外需要说明的是可以制定图像绕着那一点旋转,我们只要指定它的描点,在rotation方法里面加入下面这句代码
self.shapLayer.anchorPoint = CGPointMake(0.1, 0.1);
效果如下:



由于我们改变了描点,所以图像的fram变了。

这里strokeBoard方法里面我们设置了shapLayer的lineWidth和strokeColor,lineWidth默认是0,strokeColor默认是透明的。
当lineWidth非0时,显示方法是内外各一半。为了便于观察,这里运行前把上面的描点的那句代码注释掉,运行效果如下:


抖动动画
上一篇下一篇

猜你喜欢

热点阅读