16-核心动画

2016-03-31  本文已影响22人  木喳喳的夏天

画板(图片处理)

隐式动画

时钟动画

// 一秒钟秒针转6°
#define perSecondA 6

// 一分钟分针转6°
#define perMinuteA 6

// 一小时时针转30°
#define perHourA 30

// 每分钟时针转多少度
#define perMinuteHourA 0.5
@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *clockView;

@property (nonatomic, weak) CALayer *secondLayer;

@property (nonatomic, weak) CALayer *minuteLayer;

@property (nonatomic, weak) CALayer *hourLayer;

@end
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    // 添加时针,因为先添加的在下面
    [self setUpHourLayer];
    
    // 添加分针
    [self setUpMinuteLayer];
    
    // 添加秒针
    [self setUpSecondLayer];
    
    // 添加定时器
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
    
    [self timeChange];
    
}
#pragma mark - 添加秒针
- (void)setUpSecondLayer
{
   CALayer *secondL = [CALayer layer];
    
    secondL.backgroundColor = [UIColor redColor].CGColor;
    
    // 设置锚点
    secondL.anchorPoint = CGPointMake(0.5, 1);
    
    secondL.position = CGPointMake(kClockW * 0.5, kClockW * 0.5);
    
    secondL.bounds = CGRectMake(0, 0, 1, kClockW * 0.5 - 20);
    
    [_clockView.layer addSublayer:secondL];
    
    _secondLayer = secondL;
}

#pragma mark - 添加分针
- (void)setUpMinuteLayer
{
    CALayer *layer = [CALayer layer];
    
    layer.backgroundColor = [UIColor blackColor].CGColor;
    
    // 设置锚点
    layer.anchorPoint = CGPointMake(0.5, 1);
    
    layer.position = CGPointMake(kClockW * 0.5, kClockW * 0.5);
    
    layer.bounds = CGRectMake(0, 0, 4, kClockW * 0.5 - 20);
    
    layer.cornerRadius = 4;
    
    [_clockView.layer addSublayer:layer];
    
    _minuteLayer = layer;
}

#pragma mark - 添加时针
- (void)setUpHourLayer
{
    CALayer *layer = [CALayer layer];
    
    layer.backgroundColor = [UIColor blackColor].CGColor;
    
    // 设置锚点
    layer.anchorPoint = CGPointMake(0.5, 1);
    
    layer.position = CGPointMake(kClockW * 0.5, kClockW * 0.5);
    
    layer.bounds = CGRectMake(0, 0, 4, kClockW * 0.5 - 40);
    
    layer.cornerRadius = 4;
    
    [_clockView.layer addSublayer:layer];
    
    _hourLayer = layer;
}
- (void)timeChange
{
    // 获取当前的系统的时间
    
    // 获取当前日历对象
    NSCalendar *calendar = [NSCalendar currentCalendar];
    
    // 获取日期的组件:年月日小时分秒
    // components:需要获取的日期组件
    // fromDate:获取哪个日期的组件
    // 经验:以后枚举中有移位运算符,通常一般可以使用并运算(|)
    NSDateComponents  *cmp = [calendar components:NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour fromDate:[NSDate date]];
    
    // 获取秒
    NSInteger second = cmp.second;
    
    // 获取分
    NSInteger minute = cmp.minute;
    
    // 获取小时
    NSInteger hour = cmp.hour;
    
    // 计算秒针转多少度
    CGFloat secondA = second * perSecondA;
    
    // 计算分针转多少度
    CGFloat minuteA = minute * perMinuteA;
    
    // 计算时针转多少度
    CGFloat hourA = hour * perHourA + minute * perMinuteHourA;
    
    // 旋转秒针
    _secondLayer.transform = CATransform3DMakeRotation(angle2radion(secondA), 0, 0, 1);
    
    // 旋转分针
    _minuteLayer.transform = CATransform3DMakeRotation(angle2radion(minuteA), 0, 0, 1);
    
    // 旋转小时
    _hourLayer.transform = CATransform3DMakeRotation(angle2radion(hourA), 0, 0, 1);
}

核心动画(CABasicAnimation)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 创建动画
    CABasicAnimation *anim = [CABasicAnimation animation];
    
    // 描述下修改哪个属性产生动画
    // anim.keyPath = @"position";
    // 只能是layer属性
    anim.keyPath = @"transform.scale";
    
    // 设置值
    // anim.toValue = [NSValue valueWithCGPoint:CGPointMake(250, 500)];
    
    anim.toValue = @0.5;
    
    // 设置动画执行次数
    anim.repeatCount = MAXFLOAT;
    
    // 取消动画反弹
    // 设置动画完成的时候不要移除动画
    anim.removedOnCompletion = NO;
    
    // 设置动画执行完成要保持最新的效果
    anim.fillMode = kCAFillModeForwards;
    
    [_imageV.layer addAnimation:anim forKey:nil];
    
}

核心动画(CAKeyFrameAnimation)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // touch
    UITouch *touch = [touches anyObject];
    
    // 获取手指的触摸点
    CGPoint curP = [touch locationInView:self];
    
    // 创建路径
    UIBezierPath *path = [UIBezierPath bezierPath];
    _path = path;
    
    // 设置起点
    [path moveToPoint:curP];
    
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // touch
    UITouch *touch = [touches anyObject];
    
    // 获取手指的触摸点
    CGPoint curP = [touch locationInView:self];
    
    [_path addLineToPoint:curP];
    
    [self setNeedsDisplay];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 给imageView添加核心动画
    // 添加核心动画
    
    CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
    
    anim.keyPath = @"position";
    
    // anim.values = @[@(angle2Radion(-10)),@(angle2Radion(10)),@(angle2Radion(-10))];
    
    anim.path = _path.CGPath;
    
    anim.duration = 1;
    
    anim.repeatCount = MAXFLOAT;
    
    [[[self.subviews firstObject] layer] addAnimation:anim forKey:nil];
}

核心动画(CATransition)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    
    // 转场代码
    if (i == 4) {
        i = 1;
    }
    // 加载图片名称
    NSString *imageN = [NSString stringWithFormat:@"%d",i];
    
    _imageView.image = [UIImage imageNamed:imageN];
    
    i++;
    
    // 转场动画
    CATransition *anim = [CATransition animation];
    
    anim.type = @"pageCurl";
    
    anim.duration = 2;
    
    [_imageView.layer addAnimation:anim forKey:nil];
    
}

核心动画(CAAnimationGroup)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 同时缩放,平移,旋转
    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 = @(arc4random_uniform(M_PI));
    
    CABasicAnimation *position = [CABasicAnimation animation];
    position.keyPath = @"position";
    position.toValue = [NSValue valueWithCGPoint:CGPointMake(arc4random_uniform(200), arc4random_uniform(200))];
    
    group.animations = @[scale,rotation,position];
    
    [_redView.layer addAnimation:group forKey:nil];
    
}

UIView和核心动画(Core Animation)的区别

// 动画完成的时候调用
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    NSLog(@"%@", NSStringFromCGPoint(_redView.layer.position));
}
    [UIView animateWithDuration:0.25 animations:^{
        
        _redView.layer.position = CGPointMake(150, 400);

    } completion:^(BOOL finished) {

            NSLog(@"%@", NSStringFromCGPoint(_redView.layer.position));

        }];

转盘的设计

+ (instancetype)wheelView
{
   return  [[NSBundle mainBundle] loadNibNamed:@"WheelView" owner:nil options:nil][0];
}
- (void)awakeFromNib
{
    // UIImageView是个比较特殊的View,默认不会与用户进行交互,需要设置userInteractionEnabled为YES
    _centerView.userInteractionEnabled = YES;
    CGFloat btnW = 68;
    CGFloat btnH = 143;
    
     CGFloat wh = self.bounds.size.width;
    
    // 加载大图片
    UIImage *bigImage = [UIImage imageNamed:@"LuckyAstrology"];
    
    // 加载大图片
    UIImage *selBigImage = [UIImage imageNamed:@"LuckyAstrologyPressed"];
    
    // 获取当前使用的图片像素和点的比例
    CGFloat scale = [UIScreen mainScreen].scale;
    CGFloat imageW = bigImage.size.width / 12 * scale;
    CGFloat imageH = bigImage.size.height * scale;
    // CGImageRef image:需要裁减的图片
    // rect:裁减区域
    // 裁减区域是以像素为基准
    // CGImageCreateWithImageInRect(CGImageRef image, CGRect rect)
    
    // 添加按钮
    for (int i = 0; i < 12; i++) {
        WheelButton *btn = [WheelButton buttonWithType:UIButtonTypeCustom];
        
        // 设置按钮的位置
        btn.layer.anchorPoint = CGPointMake(0.5, 1);
        
        btn.bounds = CGRectMake(0, 0, btnW, btnH);
        
        btn.layer.position = CGPointMake(wh * 0.5, wh * 0.5);
        
        // 按钮的旋转角度
        CGFloat radion = (30 * i) / 180.0 * M_PI;
        
        btn.transform = CGAffineTransformMakeRotation(radion);
        
        [_centerView addSubview:btn];
        
        // 加载按钮的图片
        // 计算裁减区域
        CGRect clipR = CGRectMake(i * imageW, 0, imageW, imageH);
        
        // 裁减图片
        CGImageRef imgR =  CGImageCreateWithImageInRect(bigImage.CGImage, clipR);
        
        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];
        }
        
    }
}

- (void)btnClick:(UIButton *)btn
{
    _selBtn.selected = NO;
    btn.selected = YES;
    _selBtn = btn;
}
#pragma mark - 开始旋转
- (void)start
{
    CABasicAnimation *anim = [CABasicAnimation animation];
    
    anim.keyPath = @"transform.rotation";
    
    anim.toValue = @(M_PI * 2);
    
    anim.duration = 2;
    
    anim.repeatCount = MAXFLOAT;
    
    [_centerView.layer addAnimation:anim forKey:nil];
}
// 设置UIImageView的尺寸
// contentRect:按钮的尺寸
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    // 计算UIImageView控件尺寸
    CGFloat imageW = 40;
    CGFloat imageH = 46;
    CGFloat imageX = (contentRect.size.width - imageW) * 0.5;
    CGFloat imageY = 20;
    return CGRectMake(imageX, imageY, imageW, imageH);
}

// 取消高亮状态
- (void)setHighlighted:(BOOL)highlighted
{
    
}
上一篇下一篇

猜你喜欢

热点阅读