Core Animation一些Demo总结 (动态切换图片、大转盘、图片折叠、进

2019-12-10 19:03:23王旭

二、彩票转盘

这个动画的实现主要难点在于Button的摆放,只要摆放好button,其他就是简单的添加动画的一个过程。

12个星座,那么需要12个button。在摆放它们的时候,我是将一个个button的anchorPoint设置为(0.5, 1),将button的position设置为中心圆的圆心,然后设置transform来旋转它们,是的达到围绕一个圆摆放的目的。

需要知道的是,一般来说,控件的anchorPoint就是控件的中心点,所以在我们做旋转、平移等操作的时候,也就是在围绕中心点的一系列操作。但是,很多时候,只是围绕中心点来设置动画的话,会很复杂,CALayer提供了一个anchorPoint属性,可以让我们自由的改变其数值,从而实现比较复杂的动画。

还有就是button的点击事件,事实上由于一个扇形区域是上边大,下边小,要是不做相应的限制,当用户点击下面的区域时,很可能不是选中当前的button,因此要做一定的限制。这里我是自定义了一个button,在里面重写了hitTest: WwthEvent: 方法,这个方法可以设置你所要监听事件的区域范围。

代码:

#import "ZYWheelView.h"
#define ZYImageW 40
#define ZYImageH 46
@interface ZYButton : UIButton
@end
@implementation ZYButton

/**
* 重写此方法,截取button的点击
*
*/
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
CGFloat btnW = self.bounds.size.width;
CGFloat btnH = self.bounds.size.height;
CGFloat x = 0;
CGFloat y = btnH / 2;
CGFloat w = btnW;
CGFloat h = y;
CGRect rect = CGRectMake(x, y, w, h);
if (CGRectContainsPoint(rect, point)) {
return nil;
}else{
return [super hitTest:point withEvent:event];
}
}
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
CGFloat imageX = (contentRect.size.width - ZYImageW ) * 0.5;
CGFloat imageY = 18;
return CGRectMake(imageX, imageY, ZYImageW, ZYImageH);
}
- (void)setHighlighted:(BOOL)highlighted
{ 
}
@end
@interface ZYWheelView ()
@property (weak, nonatomic) IBOutlet UIImageView *wheelView;

@property (nonatomic, weak) UIButton *lastSelectedBtn;

@property (nonatomic, strong) CADisplayLink *timer;
@end
@implementation ZYWheelView
+ (instancetype)wheelView
{
return [[[NSBundle mainBundle] loadNibNamed:@"ZYWheelView" owner:nil options:nil] lastObject];
}
- (void)awakeFromNib
{
self.wheelView.userInteractionEnabled = YES;
CGFloat angle = 2 * M_PI / 12.0;

UIImage *normalImage = [UIImage imageNamed:@"LuckyAstrology"];
UIImage *selectedImage = [UIImage imageNamed:@"LuckyAstrologyPressed"];
for (int bi = 0; bi < 12; bi++) {
ZYButton *btn = [[ZYButton alloc] init];
[btn setBackgroundImage:[UIImage imageNamed:@"LuckyRototeSelected"] forState:UIControlStateSelected];
// 切割图片,将切割好的图片设置到按钮上
// CGImage中rect是当做像素来使用
// UIKit 中是点坐标系
// 坐标系的特点:如果在非retain屏上 1个点等于1个像素
// 在retain屏上1个点等于2个像素
CGFloat imageH = ZYImageH * [UIScreen mainScreen].scale;
CGFloat imageW = ZYImageW * [UIScreen mainScreen].scale;
CGFloat imageY = 0;
CGFloat imageX = bi * imageW;
CGRect rect = CGRectMake(imageX, imageY, imageW, imageH);
CGImageRef normalRef = CGImageCreateWithImageInRect(normalImage.CGImage, rect);
CGImageRef selectedRef = CGImageCreateWithImageInRect(selectedImage.CGImage, rect);
[btn setImage:[UIImage imageWithCGImage:normalRef] forState:UIControlStateNormal];
[btn setImage:[UIImage imageWithCGImage:selectedRef] forState:UIControlStateSelected];
btn.bounds = CGRectMake(0, 0, 58, 143);
btn.layer.anchorPoint = CGPointMake(0.5, 1);
btn.layer.position = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5);
btn.transform = CGAffineTransformMakeRotation(angle * bi);
[btn addTarget:self action:@selector(clickBtn:) forControlEvents:UIControlEventTouchUpInside];
[self.wheelView addSubview:btn];
}
[self startRotating];
}
- (void)startRotating
{
if (self.timer) return;
self.timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateTimer)];
[self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
- (void)stopRotating
{
[self.timer invalidate];
self.timer = nil;
}
- (void)clickBtn:(UIButton *)btn
{
self.lastSelectedBtn.selected = NO;
btn.selected = YES;
self.lastSelectedBtn = btn;
}
- (IBAction)clickCenterBtn:(id)sender {
self.userInteractionEnabled = NO;
[self stopRotating];
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
basicAnimation.toValue = @(M_PI * 2 * 5);
basicAnimation.duration = 2;
basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
// basicAnimation.removedOnCompletion = NO;
// basicAnimation.fillMode = kCAFillModeForwards;
basicAnimation.delegate = self;
[self.wheelView.layer addAnimation:basicAnimation forKey:nil];
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
self.userInteractionEnabled = YES;
// 根据选中的按钮获取旋转的度数,
// 通过transform获取角度
CGFloat angle = atan2(self.lastSelectedBtn.transform.b, self.lastSelectedBtn.transform.a);
// 从实际上旋转转盘
self.wheelView.transform = CGAffineTransformMakeRotation(-angle);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self startRotating];
}); 
}
- (void)updateTimer
{
self.wheelView.transform = CGAffineTransformRotate(self.wheelView.transform, M_PI / 200);
}
- (void)dealloc
{
[self stopRotating];
}
@end