iOS 抽奖转盘 练习demo

组里到了新的6+,为了搞一轮抽奖写了这个抽奖程序。

首先我们要有权重数据,最近在看权利的游戏,给喜欢的人物加分: 如果你要改成自己的数据只要修改这里就可以了

 1     NSDictionary *dataDic = [NSDictionary
 2                              dictionaryWithObjectsAndKeys:
 3                              @(1),@"Jamie",
 4                              @(1),@"Cersei", 
 5                              @(1),@"Joffery",
 6                              @(3),@"Imp",
 7                              @(1),@"Ned",
 8                              @(4),@"Arrey",
 9                              @(2),@"Shae",
10                              @(2),@"Sansa",
11                              @(4),@"Margaery",
12                              @(2),@"Baelish",
13                              nil];

 

 接下来就是画转盘。我们要画一个不管数据是什么都能够完美展现的转盘。转盘的公平性就在于对 360度要根据每个人的权重进行均分。那么我们首先就要对权重数据进行处理,将权重变成角度。

 1 - (void)setData:(NSDictionary*)dataDic
 2 {
 3     self.cornerDic = [[NSMutableDictionary alloc]init];
 4     int totalCount = 0;
 5     for (NSString *key in dataDic) {
 6         totalCount += [(NSNumber*)dataDic[key] intValue];
 7     }
 8     
 9     for (NSString *key in dataDic) {
10         double corner = [(NSNumber*)dataDic[key] doubleValue]/(double)totalCount * 360;
11         [self.cornerDic setObject:@(corner) forKey:key];
12     }
13 }

好了现在数据已备好,可以开始画了。画转盘的关键有两点:1.如何画扇形; 2.如何把人名旋转一个合适的角度让它正确的显示在对应的扇形上。

 1 static inline void drawArc(CGContextRef ctx, CGPoint point, float radius,float angle_start, float angle_end, UIColor* color)
 2 {
 3     //设置填充颜色
 4     CGContextSetFillColor(ctx, CGColorGetComponents( [color CGColor]));
 5     //移动画笔
 6     CGContextMoveToPoint(ctx, point.x, point.y);
 7     //画扇形
 8     CGContextAddArc(ctx, point.x, point.y, radius,  angle_start, angle_end, 0);
 9     //填充
10     CGContextFillPath(ctx);
11 
12     //画中间的白色分割线
13     CGContextSetRGBStrokeColor(ctx, 1, 1, 1, 1);
14     //设置线条宽度
15     CGContextSetLineWidth(ctx, 2);
16     CGContextMoveToPoint(ctx, point.x, point.y);
17     //算出线另一端的坐标
18     CGPoint point1 = CGPointMake(point.x + radius*cos(angle_start), point.y + radius*sin(angle_start));
19     //画线
20     CGContextAddLineToPoint(ctx, point1.x, point1.y);
21     CGContextStrokePath(ctx);
22 }

 

那么为什么一定要在drawRect里写绘制的代码呢?在外面行不行呢?貌似是不行。(如果以后知道有会贴回来)因为所有的绘制都需要一个“上下文环境”。而这个上下文只有在drawRect里才能获取到值,在外面拿到的都是nil。

“The current graphics context is nil by default. Prior to calling its drawRect: method, view objects push a valid context onto the stack, making it current. If you are not using a UIView object to do your drawing, however, you must push a valid context onto the stack manually using the UIGraphicsPushContext function."

 1 - (void)drawRect:(CGRect)rect
 2 {
 3     CGContextRef ctx = UIGraphicsGetCurrentContext();
 4     CGContextClearRect(ctx, rect);
 5 
 6     srand((unsigned)time(0));
 7     
 8     CGPoint center = CGPointMake(self.frame.size.width/2, self.frame.size.width/2);
 9     
10     float angle_start = 0;
11     float angle_end = 0;
12     int i = 0;
13     
14     
15     UIColor *yelloColor = [UIColor colorWithRed:249/255.0 green:226/255.0 blue:55/255.0 alpha:1];
16     UIColor *redColor = [UIColor colorWithRed:247/255.0 green:148/255.0 blue:53/255.0 alpha:1];
17     
18     //遍历字典,画饼
19     for (NSString *key in self.cornerDic) {
20 //        if ([key isEqualToString:@"Imp"]) {
21         
22         angle_start = angle_end;
23         angle_end = angle_start+ radians([(NSNumber*)self.cornerDic[key] doubleValue]);
24         
25         UIColor *color = nil;
26         if (i%2 == 0) {
27             color = yelloColor;
28         }
29         else
30         {
31             color = redColor;
32         }
33         //画扇形
34         drawArc(ctx, center, self.frame.size.width/2-self.layer.borderWidth, angle_start, angle_end, color);
35         i++;
36 
37         CATextLayer *txtLayer = [self textLayer:key rotate:angle_start + (angle_end-angle_start)/2];
38         [self.layer addSublayer:txtLayer];
39 //        }
40     }
41 }

画人名我用了CATextLayer这个东西,可设置的东西还挺多的。我把文字设置在右边,这样旋转角更好设置。我在调试过程中经常把控件的背景颜色变成醒目的颜色,这样更好调试UI。

 1     CATextLayer *txtLayer = [CATextLayer layer];
 2     //设置每个layer的长度都为转盘的直径
 3     txtLayer.frame = CGRectMake(0, 0, self.frame.size.width-self.layer.borderWidth*2-8, 25);
 4     
 5     //设置锚点,绕中心点旋转
 6     txtLayer.anchorPoint = CGPointMake(0.5, 0.5);
 7     txtLayer.string = text;
 8     txtLayer.alignmentMode = [NSString stringWithFormat:@"right"];
 9     txtLayer.fontSize = 18;
10     
11     //layer没有center,用Position
12     [txtLayer setPosition:CGPointMake(self.frame.size.width/2, self.frame.size.width/2)];
13     //旋转
14     txtLayer.transform = CATransform3DMakeRotation(angel,0,0,1);
15     return txtLayer;

最后就是让这个转盘旋转起来,用随机数得到旋转的弧度。

 1 - (void)turnTheTable
 2 {
 3     CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];//z的意思是绕z轴旋转,此处的z轴是垂直于iPhone,正方向从背面指向屏幕前方
 4     double endValue = _startValue+(rand()%100)/100.0 * M_PI + M_PI*(rand()%5+5); //这里的endValue单位是弧度,2PI是一圈
 5     
 6     //设置旋转的起始值与终止值
 7     rotationAnimation.fromValue = @(_startValue);
 8     rotationAnimation.toValue = @(endValue);
 9     
10     //旋转时长
11     rotationAnimation.duration = (endValue - _startValue)/(M_PI*2);
12     rotationAnimation.autoreverses = NO;
13     
14     //速度函数
15     rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
16     rotationAnimation.removedOnCompletion = NO;
17     rotationAnimation.fillMode = kCAFillModeBoth;
18     [self.turnTableView.layer addAnimation:rotationAnimation forKey:@"TurnTableAnimation"];
19     
20     //记下当前旋转的位置,作为下一次旋转的起始值
21     _startValue = endValue;
22 }

 

 完整工程地址:https://github.com/MeowWang/LotteryTurnTable

 

转载请注明出处

posted @ 2015-08-25 18:29  夏哔哔  阅读(2467)  评论(0编辑  收藏  举报