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

 

轉載請注明出處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM