Core AnimationiOS Developer动画

iOS图层配合核心动画详解

2017-01-24  本文已影响770人  45b645c5912e

Core Animation

Core Animation的使用步骤

CAAnimation

-(void)animationDidStart:(CAAnimation *)anim;
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
#pragma mark 暂停CALayer的动画
-(void)pauseLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];

    // 让CALayer的时间停止走动
      layer.speed = 0.0;
    // 让CALayer的时间停留在pausedTime这个时刻
    layer.timeOffset = pausedTime;
}
#pragma mark 恢复CALayer的动画
-(void)resumeLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = layer.timeOffset;
    // 1. 让CALayer的时间继续行走
      layer.speed = 1.0;
    // 2. 取消上次记录的停留时刻
      layer.timeOffset = 0.0;
    // 3. 取消上次设置的时间
      layer.beginTime = 0.0;    
    // 4. 计算暂停的时间(这里也可以用CACurrentMediaTime()-pausedTime)
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    // 5. 设置相对于父坐标系的开始时间(往后退timeSincePause)
      layer.beginTime = timeSincePause;
}

CABasicAnimation——基本动画

    //位移动画
    CABasicAnimation * positionAnim = [CABasicAnimation animation];
    positionAnim.keyPath = @"position";
    positionAnim.toValue = [NSValue valueWithCGPoint:CGPointMake(self.positionImageV.center.x+200, self.positionImageV.center.y)];
    // 设置动画执行次数
    positionAnim.repeatCount = MAXFLOAT;
    // 取消动画反弹
    // 设置动画完成的时候不要移除动画
    positionAnim.removedOnCompletion = NO;
    // 设置动画执行完成要保持最新的效果
    positionAnim.fillMode = kCAFillModeForwards;
    positionAnim.duration =2;
    [self.positionImageV.layer addAnimation:positionAnim forKey:nil];
    //创建一个基本形变动画
    CABasicAnimation * scaleAnim = [CABasicAnimation animation];
    //kvc设置需要动画的属性
    scaleAnim.keyPath = @"transform.scale";
    //设置该属性的最终装填
    scaleAnim.toValue = @0.5;
    // 设置动画执行次数
    scaleAnim.repeatCount = MAXFLOAT;
    // 取消动画反弹
    // 设置动画完成的时候不要移除动画
    scaleAnim.removedOnCompletion = NO;
    // 设置动画执行完成要保持最新的效果
    scaleAnim.fillMode = kCAFillModeForwards;
    //设置动画时间
    scaleAnim.duration =2;
    [self.scaleImageV.layer addAnimation:scaleAnim forKey:nil];
    //旋转动画
    CABasicAnimation * rotationAnim = [CABasicAnimation animation];
    rotationAnim.keyPath = @"transform.rotation";
    rotationAnim.toValue = @M_PI;
    // 设置动画执行次数
    rotationAnim.repeatCount = MAXFLOAT;
    // 取消动画反弹
    // 设置动画完成的时候不要移除动画
    rotationAnim.removedOnCompletion = NO;
    // 设置动画执行完成要保持最新的效果
    rotationAnim.fillMode = kCAFillModeForwards;
    rotationAnim.duration =2;
    [self.rotationImageV.layer addAnimation:rotationAnim forKey:nil];

CAKeyframeAnimation——关键帧动画

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    //获取touch对象
    UITouch * touch = [touches anyObject];
    //获取手指位置
    CGPoint fingerP = [touch locationInView:self];
    //创建一个路径并保存
    UIBezierPath * path = [UIBezierPath bezierPath];
    self.path = path;
    //路径添加起点
    [path moveToPoint:fingerP];
}

2 手指在view上移动时

-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    UITouch * touch = [touches anyObject];
    CGPoint fingerP = [touch locationInView:self];
    //不断连线,
    [self.path addLineToPoint:fingerP];
    [self setNeedsDisplay];
}

3 手指离开view时

-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//创建一个帧动画
    CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
    //动画需要改变的属性
    anim.keyPath = @"position";
    //动画的改变的路径
    anim.path = _path.CGPath;
    //动画的时间
    anim.duration = 1;
    //动画的重复次数
    anim.repeatCount = MAXFLOAT;
    [[[self.subviews firstObject] layer] addAnimation:anim forKey:nil];
}

4 重绘方法drawRect

-(void)drawRect:(CGRect)rect{
    //划线
    [self.path stroke];
}

CAAnimationGroup——动画组

// 同时缩放,平移,旋转
    //创建一个动画组
    CAAnimationGroup *group = [CAAnimationGroup animation];
    //形变动画
    CABasicAnimation *scale = [CABasicAnimation animation];
    scale.keyPath = @"transform.scale";
    scale.toValue = @0.5;
    //旋转动画
    CABasicAnimation *rotation = [CABasicAnimation animation];
    rotation.keyPath = @"transform.rotation";
    rotation.toValue = @(M_PI);
    //位移动画
    CABasicAnimation *position = [CABasicAnimation animation];
    position.keyPath = @"position";
    position.toValue = [NSValue valueWithCGPoint:CGPointMake(self.imageView.center.x+200,self.imageView.center.y)];
    //动画组时间
    group.duration = 2;
    //动画组重复
    group.repeatCount = MAXFLOAT;
    //三个基本动画添加到动画组中
    group.animations = @[scale,rotation,position];
    [self.imageView.layer addAnimation:group forKey:nil];
}

转场动画——CATransition

// 加载图片名称
    NSString *imageN = [NSString stringWithFormat:@"%d",i];  
    _imageView.image = [UIImage imageNamed:imageN];
    i++;
    // 转场动画
    CATransition *anim = [CATransition animation];
    //动画设置代理
    anim.delegate = self;
    //动画类型 苹果封装好多种类型
    anim.type = @"pageCurl";
    anim.duration = 2;
    [_imageView.layer addAnimation:anim forKey:nil];
转场动画.jpeg

使用UIView动画函数实现转场动画

+(void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;
+(void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion;

CADisplayLink

// 创建定时器
//    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timeChange)];
    // 添加主运行循环
    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

隐式动画

 //宽度和高度
@property CGRect bounds;
//位置(默认指中点,具体由anchorPoint决定)
@property CGPoint position;
//锚点(x,y的范围都是0-1),决定了position的含义
@property CGPoint anchorPoint;
//背景颜色(CGColorRef类型)
@property CGColorRef backgroundColor;
//形变属性
@property CATransform3D transform;
//边框颜色(CGColorRef类型)
@property CGColorRef borderColor;
//边框宽度
@property CGFloat borderWidth;
//圆角半径
@property CGColorRef borderColor;
//内容(比如设置为图片CGImageRef)
@property(retain) id contents;
//用来设置CALayer在父层中的位置
//以父层的左上角为原点(0, 0)
@property CGPoint position;
//称为“定位点”、“锚点”
//决定着CALayer身上的哪个点会在position属性所指的位置
//以自己的左上角为原点(0, 0)
//它的x、y取值范围都是0~1,默认值为(0.5, 0.5)
@property CGPoint anchorPoint;
//创建一个图层 (只有新创建的图层才可以有隐式动画)
    CALayer * layer = [[CALayer alloc] init];
    //设置大小
    layer.bounds = CGRectMake(0, 0, 80, 80);
    //设置颜色
    layer.backgroundColor = [self randomColor].CGColor;
    //设置位置点
    layer.position = CGPointMake(200, 150);
    //图层加载到view上
    [self.view.layer addSublayer:layer];
    self.layer = layer;
#define angle2radion(angle) angle / 180 * M_PI
-(void)beginAnimation{
    //3D旋转
    self.layer.transform = CATransform3DMakeRotation(angle2radion(arc4random_uniform(360)), 0, 0, 1);
    //3D移动
    self.layer.position = CGPointMake(arc4random_uniform(200)+20, arc4random_uniform(400)+50);
    self.layer.cornerRadius = arc4random_uniform(50);
    self.layer.backgroundColor = [self randomColor].CGColor;
    self.layer.borderColor = [self randomColor].CGColor;
    self.layer.borderWidth = arc4random_uniform(10);
}
//随机产生颜色
-(UIColor *)randomColor{
    CGFloat r = arc4random_uniform(256) / 255.0;
    CGFloat g = arc4random_uniform(256) / 255.0;
    CGFloat b = arc4random_uniform(256) / 255.0;
    return [UIColor colorWithRed:r green:g blue:b alpha:1];
}

转盘效果

#pragma mark - xib加载后创建12个按钮
-(void)awakeFromNib{
    [super awakeFromNib];
    //设置按钮父控件可以交互
    self.rotationView.userInteractionEnabled = YES;
    //按钮的宽高
    CGFloat btnW = 68;
    CGFloat btnH = 143;
    //view的宽高
    CGFloat wh = self.bounds.size.width;
    //12张按钮图片是连一起的一张大图 需要裁剪
    UIImage *bigImage = [UIImage imageNamed:@"LuckyAstrology"];
    //select状太下的图片
    UIImage *selBigImage = [UIImage imageNamed:@"LuckyAstrologyPressed"];
    //获取像素与点的比值
    CGFloat scale = [UIScreen mainScreen].scale;
    //每个图片的宽度
    CGFloat imageW = bigImage.size.width / 12 * scale;
    //每个图片的高度
    CGFloat imageH = bigImage.size.height * scale;
    for (int i = 0; i < 12; i ++) {
        //每个图片需要旋转的角度
        CGFloat angle = (30 * i) / 180.0 * M_PI;
        //自定义按钮
        TurnBtn * btn = [TurnBtn buttonWithType:UIButtonTypeCustom];
        //大小
        btn.bounds = CGRectMake(0, 0, btnW, btnH);
        //设置position 和anchorPoint 因为要旋转每个按钮
        btn.layer.anchorPoint = CGPointMake(0.5, 1);
        btn.layer.position = CGPointMake(wh*0.5, wh*0.5);
        //旋转angle
        btn.transform = CGAffineTransformMakeRotation(angle);
        [self.rotationView addSubview:btn];
        //图片裁剪区域
        CGRect clipR = CGRectMake(i * imageW, 0, imageW, imageH);
        //获得裁剪后的图片
        CGImageRef imgR =  CGImageCreateWithImageInRect(bigImage.CGImage, clipR);
        //转成UIImage
        UIImage *image = [UIImage imageWithCGImage:imgR];
        [btn setImage:image forState:UIControlStateNormal];
        imgR = CGImageCreateWithImageInRect(selBigImage.CGImage, clipR);
        image = [UIImage imageWithCGImage:imgR];
        [btn setImage:image forState:UIControlStateSelected];
        //设置背景图
        [btn setBackgroundImage:[UIImage imageNamed:@"LuckyRototeSelected"] forState:UIControlStateSelected];
        [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
        if (i == 0) {
            //默认选中第一张
            [self btnClick:btn];
        }
    }
}
#pragma mark -定时器懒加载
// 1.搞个定时器,每隔一段时间就旋转一定的角度,1秒旋转45°
-(CADisplayLink *)link{
    if (!_link) {
        //CADisplayLink 定时器一秒调用60次
        _link = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotation)];
        //讲定时器添加到驻训华
        [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    }
    return _link;
}
#pragma mark - 定时器绑定的旋转方法
-(void)rotation{
    // 每一次调用旋转多少 45 \ 60.0
    CGFloat angle = (45 / 60.0) * M_PI / 180.0;
    self.rotationView.transform = CGAffineTransformRotate(self.rotationView.transform, angle);
}
#pragma mark - 开始旋转的方法
-(void)start{
    self.link.paused = NO;
}
#pragma mark - 暂停旋转的方法
-(void)purase {
    self.link.paused = YES;
}
#pragma mark -选号点击
-(IBAction)pickerClick:(id)sender {
    // 不需要定时器旋转
    self.link.paused = YES;
    // 中间的转盘快速的旋转,并且不需要与用户交互
    CABasicAnimation *anim = [CABasicAnimation animation];
    anim.keyPath = @"transform.rotation";
    anim.toValue = @(M_PI * 2 * 3);
    anim.duration = 0.5;
    anim.delegate = self;
    [self.rotationView.layer addAnimation:anim forKey:nil];
    // 点击哪个星座,就把当前星座指向中心点上面
    // M_PI 3.14
    // 根据选中的按钮获取旋转的度数,
    // 通过transform获取角度
    CGFloat angle = atan2(self.btn.transform.b, self.btn.transform.a);
    // 旋转转盘
    self.rotationView.transform = CGAffineTransformMakeRotation(-angle);
}

图片折叠

-(void)setImage:(UIImage *)image{
    _image = image;
    //给两张图片赋值
    self.topImageV.image = _image;
    //让上部图片只显示图片的上部分
    self.topImageV.layer.contentsRect = CGRectMake(0, 0, 1, 0.5);
    self.bottomImageV.image = _image;
    //让下部图片只显示图片的下部分
    self.bottomImageV.layer.contentsRect = CGRectMake(0, 0.5, 1, 0.5);
}
//两张重叠的图片设置锚点
   self.topImageV.layer.anchorPoint = CGPointMake(0.5, 1);
   self.bottomImageV.layer.anchorPoint = CGPointMake(0.5, 0);
 //渐变图层
    CAGradientLayer * gradientL = [CAGradientLayer layer];
    gradientL.frame = self.bottomImageV.bounds;
    //渐变颜色数组
    gradientL.colors = @[(id)[UIColor clearColor].CGColor,(id)[UIColor blackColor].CGColor];
    gradientL.opacity = 0;
    self.gradientL = gradientL;
    //添加到底部imageView
    [self.bottomImageV.layer addSublayer:gradientL];
-(void)pan:(UIPanGestureRecognizer *)pan{
    //获得手指偏移量
    CGPoint curP = [pan translationInView:self];
    //根据手指偏移量设置3D旋转角度
    CGFloat angle = - curP.y / self.frame.size.height * M_PI;
    //复位
    CATransform3D transfrom = CATransform3DIdentity;
    // 增加旋转的立体感,近大远小,d:距离图层的距离
    transfrom.m34 = -1 / 500.0;
    //3D旋转
    transfrom = CATransform3DRotate(transfrom, angle, 1, 0, 0);
    //旋转上部图片
    self.topImageV.layer.transform = transfrom;
    //设置渐变图层的透明度
    self.gradientL.opacity = curP.y * 1.0 / self.frame.size.height;
    //手势结束时
    if (pan.state == UIGestureRecognizerStateEnded) {
        //弹簧效果的物理动画
        [UIView animateWithDuration:0.25 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:10 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            //恢复顶部图片
            self.topImageV.layer.transform = CATransform3DIdentity;
            //隐藏渐变图层
            self.gradientL.opacity = 0;
            
        } completion:^(BOOL finished) {
            
        }];
    }
}

复制图层CAReplicatorLayer

音量振动条
/创建一个复制图层
    CAReplicatorLayer * repL = [CAReplicatorLayer layer];
    //设置复制图层的大小
    repL.frame = self.bounds;
    //添加复制图层
    [self.layer addSublayer:repL];
//创建一个图层
    CALayer * layer = [CALayer layer];
    //设置这个的位置
    layer.position = CGPointMake(15, self.frame.size.height);
    //设置图层的锚点
    layer.anchorPoint = CGPointMake(0.5, 1);
    //设置背景颜色
    layer.backgroundColor = [UIColor grayColor].CGColor;
    //设置大小
    layer.bounds = CGRectMake(0, 0, 30, 150);
    //把这个图层添加到复制图层中
    [repL addSublayer:layer];
    //创建一个动画
    CABasicAnimation * anim = [CABasicAnimation animation];
    anim.keyPath = @"transform.scale.y";
    anim.toValue = @0.1;
    anim.repeatCount = MAXFLOAT;
    //动画回到原始位置
    anim.autoreverses = YES;
    //把动画加载到layer上
    [layer addAnimation:anim forKey:nil];
//给复制图层中子图层设置transform便宜,每个图层沿x便宜45
    repL.instanceTransform = CATransform3DMakeTranslation(45, 0, 0);
    //复制4个图层 包括复制图层
    repL.instanceCount = 4;
    //每个图层一个比一个延迟一秒执行动画
    repL.instanceDelay = 0.1;
    //每个图层的颜色
    repL.instanceColor = [UIColor greenColor].CGColor;
    //每个图层颜色渐变,
    repL.instanceGreenOffset = -0.03;
指示器
//创建一个复制图层
    CAReplicatorLayer * repL = [CAReplicatorLayer layer];
    //设置图层的的大小
    repL.frame = self.bounds;
    //添加复制图层
    [self.layer addSublayer:repL];
//创建一个子图层
    CALayer * layer = [CALayer layer];
    //设置初始位置
    layer.position = CGPointMake(self.frame.size.width * 0.5, 10);
    //设置子图层大小
    layer.bounds = CGRectMake(0, 0, 5, 5);
    //设置图层的背景颜色
    layer.backgroundColor = [UIColor purpleColor].CGColor;
    //默认形变为0是不显示的
    layer.transform = CATransform3DMakeScale(0, 0, 0);
    //把图层添加到复制图层中
    [repL addSublayer:layer];
    //创建一个动画
    CABasicAnimation * anim = [CABasicAnimation animation];
    //设置形变
    anim.keyPath = @"transform.scale";
    anim.fromValue = @1;
    anim.toValue = @0;
    anim.repeatCount = MAXFLOAT;
    CGFloat duration = 1;
    anim.duration = duration;
    [layer addAnimation:anim forKey:nil];
//20个子图层
    repL.instanceCount = count;
    repL.instanceDelay = duration / count;
    //每个子图层transform旋转偏移
    CGFloat angle = M_PI * 2 / count;
    repL.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1);
倒影效果
+(Class)layerClass
{
    return [CAReplicatorLayer class];
}
    CAReplicatorLayer *layer =  (CAReplicatorLayer *)self.layer;
    layer.anchorPoint = CGPointMake(0.5, 1);   
    layer.instanceCount = 3;
    // 往下面平移控件的高度
    layer.instanceTransform = CATransform3DMakeRotation(M_PI*0.5, 1, 0, 0);
    layer.instanceAlphaOffset = -0.1;
    layer.instanceBlueOffset = -0.1;
    layer.instanceGreenOffset = -0.1;
    layer.instanceRedOffset = -0.1;

仿QQ消息提醒(粘性效果)

//消息按钮跟随手指移动
    CGPoint tranP = [pan translationInView:self];
    CGPoint center = self.center;
    center.x += tranP.x;
    center.y += tranP.y;
    self.center = center;
    [pan setTranslation:CGPointZero inView:self];
//计算拖动圆与原位置占位圆之间的距离
    CGFloat d = [self circleCenterDistanceWithBigCircleCenter:self.center smallCircleCenter:self.backSmallView.center];
    //根据距离缩小占位圆
    CGFloat h = self.bounds.size.height*0.5;
    CGFloat smallRadius = h - d / 10;
    self.backSmallView.bounds = CGRectMake(0, 0, smallRadius * 2, smallRadius * 2);
    self.backSmallView.layer.cornerRadius = smallRadius;
#pragma mark - 计算两个圆心之间的距离
-(CGFloat)circleCenterDistanceWithBigCircleCenter:(CGPoint)bigCircleCenter smallCircleCenter:(CGPoint)smallCircleCenter
{
    CGFloat offsetX = bigCircleCenter.x - smallCircleCenter.x;
    CGFloat offsetY = bigCircleCenter.y - smallCircleCenter.y;
    
    return  sqrt(offsetX * offsetX + offsetY * offsetY);
}
#pragma mark - 不规则矩形图层(根据路径创建的图层) 懒加载
-(CAShapeLayer *)shapeLayer
{
    if (_shapeLayer == nil) {
        // 展示不规则矩形,通过不规则矩形路径生成一个图层
        CAShapeLayer *layer = [CAShapeLayer layer];
        _shapeLayer = layer;
        layer.fillColor = self.backgroundColor.CGColor;
        [self.superview.layer insertSublayer:layer below:self.layer];
    }
    return _shapeLayer;
}
#pragma mark - 描述两圆之间一条矩形路径
-(UIBezierPath *)pathWithBigCirCleView:(UIView *)bigCirCleView  smallCirCleView:(UIView *)smallCirCleView
{
    CGPoint bigCenter = bigCirCleView.center;
    CGFloat x2 = bigCenter.x;
    CGFloat y2 = bigCenter.y;
    CGFloat r2 = bigCirCleView.bounds.size.width / 2;
    CGPoint smallCenter = smallCirCleView.center;
    CGFloat x1 = smallCenter.x;
    CGFloat y1 = smallCenter.y;
    CGFloat r1 = smallCirCleView.bounds.size.width / 2;
    // 获取圆心距离
    CGFloat d = [self circleCenterDistanceWithBigCircleCenter:bigCenter smallCircleCenter:smallCenter];
    CGFloat sinθ = (x2 - x1) / d;
    CGFloat cosθ = (y2 - y1) / d;
    // 坐标系基于父控件
    CGPoint pointA = CGPointMake(x1 - r1 * cosθ , y1 + r1 * sinθ);
    CGPoint pointB = CGPointMake(x1 + r1 * cosθ , y1 - r1 * sinθ);
    CGPoint pointC = CGPointMake(x2 + r2 * cosθ , y2 - r2 * sinθ);
    CGPoint pointD = CGPointMake(x2 - r2 * cosθ , y2 + r2 * sinθ);
    CGPoint pointO = CGPointMake(pointA.x + d / 2 * sinθ , pointA.y + d / 2 * cosθ);
    CGPoint pointP =  CGPointMake(pointB.x + d / 2 * sinθ , pointB.y + d / 2 * cosθ);
    UIBezierPath *path = [UIBezierPath bezierPath];
    // A
    [path moveToPoint:pointA];
    // AB
    [path addLineToPoint:pointB];
    // 绘制BC曲线
    [path addQuadCurveToPoint:pointC controlPoint:pointP];
    // CD
    [path addLineToPoint:pointD];
    // 绘制DA曲线
    [path addQuadCurveToPoint:pointA controlPoint:pointO];
    return path;
}
#pragma mark - 手势事件
-(void)pan:(UIPanGestureRecognizer *)pan{
    
    //消息按钮跟随手指移动
    CGPoint tranP = [pan translationInView:self];
    CGPoint center = self.center;
    center.x += tranP.x;
    center.y += tranP.y;
    self.center = center;
    [pan setTranslation:CGPointZero inView:self];
    //计算拖动圆与原位置占位圆之间的距离
    CGFloat d = [self circleCenterDistanceWithBigCircleCenter:self.center smallCircleCenter:self.backSmallView.center];
    //根据距离缩小占位圆
    CGFloat h = self.bounds.size.height*0.5;
    CGFloat smallRadius = h - d / 10;
    self.backSmallView.bounds = CGRectMake(0, 0, smallRadius * 2, smallRadius * 2);
    self.backSmallView.layer.cornerRadius = smallRadius;
    if (d > kMaxDistance) {
        //当距离超过规定距离时
        // 可以拖出来
        // 隐藏占位圆
        self.backSmallView.hidden = YES;
        // 移除不规则的矩形
        [self.shapeLayer removeFromSuperlayer];
        self.shapeLayer = nil;
    }else if(d > 0 && self.backSmallView.hidden == NO){
        // 有圆心距离,并且圆心距离不大,才需要展示
        // 展示不规则矩形,通过不规则矩形路径生成一个图层
        self.shapeLayer.path = [self pathWithBigCirCleView:self smallCirCleView:self.backSmallView].CGPath;
    }
    //手势结束时 即手松开时
    if (pan.state == UIGestureRecognizerStateEnded) {
        if (d > kMaxDistance) {
            // 当圆心距离大于规定距离
            // 展示gif动画
            UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.bounds];
            NSMutableArray *arrM = [NSMutableArray array];
            for (int i = 11; i < 19; i++) {
                UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%d",i]];
                [arrM addObject:image];
            }
            imageView.animationImages = arrM;
            imageView.animationRepeatCount = 1;
            imageView.animationDuration = 0.5;
            [imageView startAnimating];
            [self addSubview:imageView];
            //延迟执行
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self removeFromSuperview];
            });
        }else{
            // 当圆心距离大于最大圆心距离
            // 移除不规则矩形
            [self.shapeLayer removeFromSuperlayer];
            self.shapeLayer = nil;
            // 还原位置
            [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.2 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{
                // 设置大圆中心点位置
                self.center = self.backSmallView.center;
            } completion:^(BOOL finished) {
                // 显示小圆
                self.backSmallView.hidden = NO;
            }];
        }
    }
}
仿QQ消息提醒.jpeg

Demo地址:(https://github.com/heiheiLqq/ZZHAnimation

上一篇 下一篇

猜你喜欢

热点阅读