iOS 果冻效果

主要了解知识点:关键帧 、贝尔塞曲线

看过很多实现果冻效果的博客,总结一下,一个超级简单的demo,初步了解动画效果比较有帮助,想要深入的就直接跳过好了。

3步实现超级简单的果冻效果:

step One:

创建一个layer子类,在这个子类中有一个属性:

/** 啫喱(果冻)变量 */

@property (nonatomic, assign)CGFloat Jelly_Var;

 

 //重写该类方法,表示如果Jelly_Var改变,就调用自己的重绘方法进行重绘,重绘方法是:-(void)drawInContext:(CGContextRef)ctx

注:该方法只会在初始化的时候调用

+(BOOL)needsDisplayForKey:(NSString *)key{

    if ([key isEqualToString:@"Jelly_Var"]) {

        return YES;

    }

    return [super needsDisplayForKey:key];

}

 

 

step Two:

重写drawInContext方法,在这里实现图像的描绘,这里主要用到贝尔塞曲线,具体的画圆曲线知识,建议问一下度娘,这里就不展开了。

-(void)drawInContext:(CGContextRef)ctx{

    //开始画动画

    

    NSString *Jelly_Var = [NSString stringWithFormat:@"调用了GooeyCircle 的 +++++++ drawInContext factor = %lf",self.Jelly_Var];

    NSLog(@"%@",Jelly_Var);

    

    self.currentRect = CGRectMake(50, 50, 50, 50);

    

    CGFloat offset =

    self.currentRect.size.width / 3.6; //设置3.6 出来的弧度最像圆形(我看一个博主是这样说的)

    CGPoint rectCenter =

    CGPointMake(self.currentRect.origin.x + self.currentRect.size.width / 2,

                self.currentRect.origin.y + self.currentRect.size.height / 2);

    

    // 8个控制点实际的偏移距离。 The real distance of 8 control points.

    CGFloat extra = (self.currentRect.size.width * 2 / 5) * (1 - self.JV_Factor);

    

    //

    CGPoint pointA = CGPointMake(rectCenter.x, self.currentRect.origin.y - extra);

    

    CGPoint pointB = CGPointMake(rectCenter.x -extra + self.currentRect.size.width /2,

                                 rectCenter.y);

    CGPoint pointC = CGPointMake(rectCenter.x , rectCenter.y + self.currentRect.size.height / 2 + extra);

    

    CGPoint pointD = CGPointMake(self.currentRect.origin.x+ extra,rectCenter.y);

    

    //

    CGPoint c1 = CGPointMake(pointA.x + offset, pointA.y);

    CGPoint c2 = CGPointMake(pointB.x, pointB.y - offset);

    

    CGPoint c3 = CGPointMake(pointB.x, pointB.y + offset);

    CGPoint c4 = CGPointMake(pointC.x + offset, pointC.y);

    

    CGPoint c5 = CGPointMake(pointC.x - offset, pointC.y);

    CGPoint c6 = CGPointMake(pointD.x, pointD.y + offset);

    

    CGPoint c7 = CGPointMake(pointD.x, pointD.y - offset);

    CGPoint c8 = CGPointMake(pointA.x - offset, pointA.y);

    

    // 更新界面

    UIBezierPath *ovalPath = [UIBezierPath bezierPath];

    [ovalPath moveToPoint:pointA];

    [ovalPath addCurveToPoint:pointB controlPoint1:c1 controlPoint2:c2];

    [ovalPath addCurveToPoint:pointC controlPoint1:c3 controlPoint2:c4];

    [ovalPath addCurveToPoint:pointD controlPoint1:c5 controlPoint2:c6];

    [ovalPath addCurveToPoint:pointA controlPoint1:c7 controlPoint2:c8];

    [ovalPath closePath];

    

    CGContextAddPath(ctx, ovalPath.CGPath);

    

    CGContextSetFillColorWithColor(ctx, [UIColor greenColor].CGColor);

    CGContextFillPath(ctx);

}

 

step Three:添加动画,创建关键帧

-(void)JV_BeginJellyAnimation{

    

    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"JV_Factor"];

    animation.values = [self JV_CreateJellyAnimationValues];

    animation.fillMode = kCAFillModeForwards;

    animation.removedOnCompletion = NO;

    animation.delegate = self;

    animation.duration = 2.0f;

    

    [self addAnimation:animation forKey:@"JellyAnimation"];

}

 

-(NSArray *)JV_CreateJellyAnimationValues{

    

    NSInteger numOfFrames = 1 * 60;//1秒

    NSMutableArray *JellyValues = [NSMutableArray arrayWithCapacity:numOfFrames];

    

    // 60个关键帧

//    NSMutableArray *values = [NSMutableArray arrayWithCapacity:numOfFrames];

    for (NSInteger i = 0; i < numOfFrames; i++) {

        [JellyValues addObject:@(0.0)];

    }

    

    CGFloat diff = 1.0f;

    for (NSInteger frame = 0; frame < numOfFrames; frame++) {

        CGFloat x = (CGFloat)frame / (CGFloat)numOfFrames;

        CGFloat value = 1 -

        diff * (pow(M_E, -5 * x) *

                cos(30 * x)); // y = 1-e^{-5x} * cos(30x)               //这个就是弹簧函数,

        JellyValues[frame] = @(value);

    }

    return JellyValues;

}

 

最后记得把动画移除,不然很耗内存

#pragma mark - delegate

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{

    [self removeAnimationForKey:@"JellyAnimation"];

}

 

+++++++++++++++++++++实现是以上三步后,就可以创建实例,然后调用方法。

 JV_Round   就是继承的Layer

self.JV_JellyRound = [JV_Round new];

        self.JV_JellyRound.frame = CGRectMake(50, 250, 150, 150);

        [self.view.layer addSublayer:self.JV_JellyRound];

 

    self.JV_JellyRound.JV_Color = [UIColor greenColor];

    self.JV_JellyRound.JV_Factor = 1.0f;

    

    [self.JV_JellyRound JV_BeginJellyAnimation];

    self.JV_JellyRound.backgroundColor = [UIColor yellowColor].CGColor;

 

 

 

http://www.cocoachina.com/ios/20150618/12171.html
http://justsee.iteye.com/blog/1972853

posted @ 2016-06-20 14:38  handsomeBoys  阅读(580)  评论(0)    收藏  举报