核心动画--关键帧动画
#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]; }