核心动画--关键帧动画

#pragma mark - 动画代理方法
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    // 取出动画类型
    NSString *type = [anim valueForKey:@"animationType"];
    
    if ([type isEqualToString:@"translationTo"]) {
        // 取出目标点 并 设置self.center
        self.center = [[anim valueForKey:@"targetPoint"]CGPointValue];
    }
    
}

#pragma mark - 私有方法
#pragma mark 生成屏幕上的随机点
- (CGPoint)randomPoint
{
    // 获得父视图的大小
    CGSize size = self.superview.bounds.size;
    
    CGFloat x = arc4random_uniform(size.width);
    CGFloat y = arc4random_uniform(size.height);
    
    return CGPointMake(x, y);
}


#pragma mark - 关键帧动画方法
/*
 在做核心动画是,一定记住动画的效果要是随机的,否则,无论多么绚丽的效果,用户都会审美疲劳!
 
 因为核心动画做的效果属于装饰性动画,动画过程中不需要用户的交互,因此动画效果就格外重要。
 */
// 使用屏幕上的随机点作为中间点,指定中间点的数量
#pragma mark 摇晃动画
// 课下练习动画的暂停和恢复
- (void)shakeAnimation
{
    // 1. 实例化关键帧动画
    CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
    
    // 晃动
//    [anim setDuration:0.5f];
    
    // 1> 角度
    CGFloat angel = M_PI_4 / 12.0;
    [anim setValues:@[@(angel), @(-angel), @(angel)]];
    
    // 2> 循环晃
    [anim setRepeatCount:HUGE_VALF];
    
    // 3. 将动画添加到图层
    [self.layer addAnimation:anim forKey:nil];
}

#pragma mark 贝塞尔曲线,两个控制点
- (void)moveCurveWithDuration:(CFTimeInterval)duration to:(CGPoint)to
{
    // 1. 实例化关键帧动画
    CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    
    // 2. 设置路径
    [anim setDuration:duration];
    
    // 中间的控制点使用屏幕上得随机点
    CGPoint cp1 = [self randomPoint];
    CGPoint cp2 = [self randomPoint];
    
    CGMutablePathRef path = CGPathCreateMutable();
    
    // 设置起始点
    CGPathMoveToPoint(path, NULL, self.center.x, self.center.y);
    // 添加带一个控制点的贝塞尔曲线
    CGPathAddCurveToPoint(path, NULL, cp1.x, cp1.y, cp2.x, cp2.y, to.x, to.y);
    
    [anim setPath:path];
    CGPathRelease(path);
    
    // 5) 设置键值记录目标位置,以便动画结束后,修正位置
    [anim setValue:@"translationTo" forKey:@"animationType"];
    [anim setValue:[NSValue valueWithCGPoint:to] forKey:@"targetPoint"];
    [anim setDelegate:self];
    
    // 3. 将动画添加到图层
    [self.layer addAnimation:anim forKey:nil];
}

#pragma mark 贝塞尔曲线,一个控制点
- (void)moveQuadCurveWithDuration:(CFTimeInterval)duration to:(CGPoint)to
{
    // 1. 实例化关键帧动画
    CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    
    // 2. 设置路径
    [anim setDuration:duration];
    
    // 中间的控制点使用屏幕上得随机点
    CGPoint cp = [self randomPoint];
    
    CGMutablePathRef path = CGPathCreateMutable();
    
    // 设置起始点
    CGPathMoveToPoint(path, NULL, self.center.x, self.center.y);
    // 添加带一个控制点的贝塞尔曲线
    CGPathAddQuadCurveToPoint(path, NULL, cp.x, cp.y, to.x, to.y);
    
    [anim setPath:path];
    CGPathRelease(path);
    
    // 5) 设置键值记录目标位置,以便动画结束后,修正位置
    [anim setValue:@"translationTo" forKey:@"animationType"];
    [anim setValue:[NSValue valueWithCGPoint:to] forKey:@"targetPoint"];
    [anim setDelegate:self];
    
    // 3. 将动画添加到图层
    [self.layer addAnimation:anim forKey:nil];
}

#pragma mark 按照矩形路径平移动画
// 移动的矩形是以当前点为矩形的一个顶点,目标点为矩形的对脚顶点
- (void)moveRectWithDuration:(CFTimeInterval)duration to:(CGPoint)to
{
    // 1. 实例化关键帧动画
    CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    
    // 2. 按照矩形移动,需要使用到路径
    [anim setDuration:duration];
    
    // 1) 创建路径
    CGMutablePathRef path = CGPathCreateMutable();
    // 2) 设置路径内容
    // 起点,宽、高
    CGFloat w = to.x - self.center.x;
    CGFloat h = to.y - self.center.y;
    CGRect rect = CGRectMake(self.center.x, self.center.y, w, h);
    CGPathAddRect(path, nil, rect);
    
    // 3) 将路径添加到动画
    [anim setPath:path];
    
    // 4) 释放路径
    CGPathRelease(path);
    
    // 3. 将动画添加到图层
    [self.layer addAnimation:anim forKey:nil];
}

#pragma mark 使用随机中心点控制动画平移
- (void)moveWithDuration:(CFTimeInterval)duration to:(CGPoint)to controlPointCount:(NSInteger)cpCount
{
    // 1. 实例化关键帧动画
    CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    
    // 2. 设置关键帧动画属性
    [anim setDuration:duration];
    
    // 设置values
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:cpCount + 2];
    
    // 1) 将起始点添加到数组
    [array addObject:[NSValue valueWithCGPoint:self.center]];
    
    // 2) 循环生成控制点位置数组
    for (NSInteger i = 0; i < cpCount; i++) {
        CGPoint p = [self randomPoint];
        
        [array addObject:[NSValue valueWithCGPoint:p]];
    }
    
    // 3) 将目标点添加到数组
    [array addObject:[NSValue valueWithCGPoint:to]];
    
    // 4) 设置values
    [anim setValues:array];
    
    // 5) 设置键值记录目标位置,以便动画结束后,修正位置
    [anim setValue:@"translationTo" forKey:@"animationType"];
    [anim setValue:[NSValue valueWithCGPoint:to] forKey:@"targetPoint"];
    [anim setDelegate:self];
    
    // 3. 将动画添加到图层
    [self.layer addAnimation:anim forKey:nil];
}
原文地址:https://www.cnblogs.com/yyh123/p/3347289.html