iOS动画案例(1) 类似于qq账号信息里的一个动画效果

2020-01-18 20:20:08刘景俊

 头像默认放第一个。


 self.head = [[UIImageView alloc] initWithFrame:[self getButtonFrame:0]];
 self.head.image = [UIImage imageNamed:@"myHead"];
 self.head.layer.borderColor = [UIColor greenColor].CGColor;
 self.head.layer.masksToBounds = YES;
 self.head.layer.cornerRadius = 25;
 self.head.layer.borderWidth = 2.0f;
 [self addSubview:self.head];

之后按钮点击之后,头像移动到按钮点击的地方。


// 按钮点击事件
- (void)buttonClick:(UIButton *)button {
 // 原来图片所在按钮的index
 int preIndex = [self getPreviousIndexByFrame:self.head.frame];
 int buttonIndex = (int)button.tag - 1;
 // 点击图片所在按钮 不做任何操作
 if (preIndex == buttonIndex) {
  return;
 }
 CGFloat width = [UIScreen mainScreen].bounds.size.width;
 float r = 2 * width / sqrt(3);
 //加入动画效果
 CALayer *transitionLayer = [[CALayer alloc] init];
 //显式事务默认开启动画效果,kCFBooleanTrue关闭 保证begin和commit 之间的属性修改同时进行
 transitionLayer.contents = self.head.layer.contents;
 transitionLayer.borderColor = [UIColor greenColor].CGColor;
 transitionLayer.masksToBounds = YES;
 transitionLayer.cornerRadius = 25;
 transitionLayer.borderWidth = 2.0f;
 transitionLayer.frame = self.head.frame;
 transitionLayer.backgroundColor=[UIColor blueColor].CGColor;
 [self.layer addSublayer:transitionLayer];
 self.head.hidden = YES;
 UIBezierPath *movePath;
 //路径曲线 贝塞尔曲线
 if (buttonIndex > preIndex) {
  // 向上滑 逆时针
  movePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0) radius:r startAngle:[self getAnticlockwiseByIndex:preIndex] endAngle:[self getAnticlockwiseByIndex:buttonIndex] clockwise:NO];
  [movePath moveToPoint:transitionLayer.position];
 }else {
  // 向下滑 顺时针
  movePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0) radius:r startAngle:[self getClockwiseAngleByIndex:preIndex] endAngle:[self getClockwiseAngleByIndex:buttonIndex] clockwise:YES];
  [movePath moveToPoint:transitionLayer.position];
 }
 //关键帧动画效果
 CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
 // 动画轨迹
 positionAnimation.path = movePath.CGPath;
 // 动画完成之后是否删除动画效果
 positionAnimation.removedOnCompletion = NO;
 // 设置开始的时间
 positionAnimation.beginTime = CACurrentMediaTime();
 CGFloat time = 0.7;
 if (labs(buttonIndex - preIndex) > 1) {
  time = 0.4 * labs(buttonIndex - preIndex);
 }
 //动画总时间
 positionAnimation.duration = time;
 // 动画的方式 淡入淡出
 positionAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
 // 执行完之后保存最新的状态
 positionAnimation.fillMode = kCAFillModeForwards;
 // 动画完成之后,是否回到原来的地方
 positionAnimation.autoreverses= NO;
 [transitionLayer addAnimation:positionAnimation forKey:@"opacity"];
 [CATransaction setCompletionBlock:^{
  [NSThread sleepForTimeInterval:time];
  self.head.hidden = NO;
  self.head.frame = button.frame;
  [transitionLayer removeFromSuperlayer];
 }];
}
// 根据Index获得顺时针的弧度
- (float)getAnticlockwiseByIndex: (NSInteger)index {
 return M_PI * (0.5 - (7.5 + 15 * index) / 180);
}
// 根据Index获得逆时针的弧度
- (float)getClockwiseAngleByIndex: (NSInteger)index {
 index = 3 - index;
 return M_PI * (30 + 7.5 + 15 * index) / 180;
}