iOS篇—Demo6—抽奖转盘

Demo6—抽奖转盘
一.搭建界面
1.设置背景图片

self.view.layer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"LuckyBackground"].CGImage);

2.自定义一个类管理转盘视图,并用xib关联界面
在这里插入图片描述

  • 创建一个xib文件,负责管理界面的基本搭建,与LuckWheelView类关联
    在这里插入图片描述
    并设置图片的大小
    在这里插入图片描述
  • 写一个类方法快速创建当前类LuckWheelView的一个对象
 + (LuckWheelView *)wheel{
    //创建当前类的一个对象
    LuckWheelView *luckView = [[[NSBundle mainBundle] loadNibNamed:@"LuckWheelView" owner:self options:nil] lastObject];
    //放回对象
    return luckView;
}
  • 在控制类中用户使用,创建转盘视图,并设置视图处于主视图中心
LuckWheelView *luckView = [LuckWheelView wheel];
luckView.center = self.view.center;
  • 让这个转盘视图显示到主视图上
[self.view addSubview:luckView];

3.当xib文件加载结束后执行后续事件

  • 由于xib中搭建的界面背景是白色的,所以,为了视觉感,将其背景颜色设为透明
self.backgroundColor = [UIColor clearColor];
  • 给转盘上添加12个按钮,不接收事件,设置按钮的中心位置为视图的中心;设置按钮的大小;设置按钮的锚点在矩形的下边线中间,以便其他按钮通过旋转形成圆盘;给按钮设置背景图片,并把各个按钮添加到转盘视图上,不可添加到主视图上,因为给主视图上添加视图是添加到主视图的最外层,会覆盖一部分视图;旋转按钮,每次循环旋转30°;给按钮上添加内容图片,表示抽奖结果。
for (int i = 0; i < 12; i++) {
        UIButton *btn = [[UIButton alloc] init];
        //设置位置
        btn.layer.position = self.center;
     
        //设置尺寸
        btn.layer.bounds = CGRectMake(0, 0, 68, 143);

        //设置锚点
        btn.layer.anchorPoint = CGPointMake(0.5, 1);
        
        //设置图片
        [btn setBackgroundImage:[UIImage imageNamed:@"LuckyRototeSelected"] forState:UIControlStateSelected];
        
        [self.wheelImageView addSubview:btn];
        
        //旋转图片
        btn.transform = CGAffineTransformRotate(btn.transform, M_PI * 2 / 12 * i);
}
  • 为了提高可移植性,把截取图片写成一个工具类别,分两步实现,第一步是已知所裁图片的名称和裁第几个,然后根据得到的图片和范围裁剪需要的那个图片。
    在这里插入图片描述
  • 第一步:先通过已知的图片名称读取图片,然后计算截取一个图片的宽高,但是为了适应不同型号的手机大小,在这里需要乘一个倍数,最后计算出裁剪的范围
 + (UIImage *)clipWithImageNamed:(NSString *)imgName index:(int)index{
    //读取图片
    UIImage *img = [UIImage imageNamed:imgName];
    //计算每一个的宽高
    CGFloat width = img.size.width / 12.0 * [UIScreen mainScreen].scale;
    CGFloat height = img.size.height * [UIScreen mainScreen].scale;
    //计算裁剪的范围
    CGRect frame = CGRectMake(index * width, 0, width, height);
    return [self clipWithImage:img rect:frame];
}
  • 第二步:算出要裁剪的范围后,调用CGImageCreateWithImageInRect方法直接裁取指定范围内的图片

CGImageRef是一个结构体指针,这个结构用来创建像素位图,可以通过操作存储的像素位来编辑图片

typedef struct CF_BRIDGED_TYPE(id) CGImage *CGImageRef;
+(UIImage *)clipWithImage:(UIImage *)img rect:(CGRect)frame{
    CGImageRef imgRef = CGImageCreateWithImageInRect(img.CGImage, frame);
    /*
    匹配屏幕大小
    参数1: cgImage:image.CGImage  image为原始图片
	参数2:scale:原始图片放大倍数
	参数3:orientation:控制image的绘制方向
	*/
    UIImage *newImage = [UIImage imageWithCGImage:imgRef scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
    return newImage;
}
  • 在for循环那里加上裁取内容图片这一步
//截取图片
UIImage *orgLongImage = [UIImage clipWithImageNamed:@"LuckyAstrology" index:i];
       
//将图片显示到按钮上
[btn setImage:orgLongImage forState:UIControlStateNormal];

二.触发事件
1.在LuckWheelView类中关联xib中开始抽奖按钮的时间
2.设置一个定时器控制转盘的开始和暂停

  • 定一个属性变量link
@property(nonatomic, strong) CADisplayLink *link;
  • 当link为空时转盘开始,不为空时转盘暂停,转盘暂停之后继续转一个角度经过一个缓冲后再停下
- (IBAction)startButtonDidClicked:(id)sender {
    if (self.link) {
        //self.link.paused = !_link.paused;
        if (self.link.paused == YES) {
            //1.暂停
            _link.paused = NO;
        } else {
            _link.paused = YES;
            //2.继续旋转一个角度
            [self stop];
        }
    } else{
        //创建定时器 执行旋转任务
        self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotate)];
        //启动定时器
        [_link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }    
}
  • 转盘开始转的方法
- (void)rotate{
    _wheelImageView.transform = CGAffineTransformRotate(_wheelImageView.transform, M_PI/30);
}

3.转盘暂停后再转一个角度缓冲并点亮箭头所指的那个按钮,首先需要计算出箭头所指方向…

- (void)stop{
    [UIView animateWithDuration:2 animations:^{
        self.wheelImageView.transform = CGAffineTransformRotate(self.wheelImageView.transform, M_PI*8/9.0);
    } completion:^(BOOL finished) {
        //确定剪头指向哪个按钮
        //1.获取旋转之后的弧度
        CGFloat hudu = [self getRadianDegreeFromTransform:self.wheelImageView.transform];
        //2.根据弧度计算旋转了几个按钮
        int index = (hudu - M_PI/12.0)/(M_PI/6.0);
        if (hudu - index*M_PI/6.0 > 0) {
            index++;
        }
        //3.通过tag值获取按钮对象
        _selectedButton = [self.wheelImageView viewWithTag:12-index+1];
        _selectedButton.selected = YES;
    }];
}
  • 计算旋转的弧度
- (CGFloat)getRadianDegreeFromTransform:(CGAffineTransform)transform{
    CGFloat rotate = acosf(transform.a);
    // 旋转180度后,需要处理弧度的变化
    if (transform.b < 0) {
        rotate = M_PI*2 - rotate;
    }
    return rotate;
}
©️2020 CSDN 皮肤主题: 终极编程指南 设计师:CSDN官方博客 返回首页