iOS抽奖转盘上篇:概率抽奖算法 & 转盘算法 &轮盘边框动画丨(内含完整Demo)
2023-02-18 16:34:23 时间
引言
原理:利用CoreGraphics进行自定义转盘的绘制
视频:https://live.csdn.net/v/158749 下载完整Demo:https://download.csdn.net/download/u011018979/16651799
在app侧控制中奖奖品,有两种方式
方式一:发起网络请求获取当前选中奖品(推荐),即由服务侧控制中奖数据,更安全 方式二:根据奖品百分比进行控制中奖概率
I、根据奖品百分比进行控制中奖概率
- 根据中奖概率probability 确定随机中奖范围probabilityRange
- 根据随机中奖范围probabilityRange,确定中奖奖品
1.1 定义奖品模型
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface KNTurntableViewModel : NSObject
@property (nonatomic, assign) NSInteger index;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *imageName;
@property (nonatomic, copy) NSString *icon;
/**
该奖品的中奖概率
*/
@property (nonatomic, assign) double probability;
//
@property (nonatomic, assign) NSRange probabilityRange;
/**
根据奖品的中奖概率获取中奖奖品
*/
+(instancetype)getMbyprobabilityRangeWithArr:(NSArray*)arr;
@end
NS_ASSUME_NONNULL_END
1.2 根据奖品的中奖概率获取中奖奖品
- 根据随机中奖范围probabilityRange,确定中奖奖品
// 根据奖品百分比进行控制:
// 奖品 title A ,index下标0,中奖 概率probability80%, 就是当randomNum为0-80,返回中奖下标0
// 为了便于理解,我们称奖品A的【随机中奖范围】 probabilityRange为0-80
//
// 根据randomNum,确定中奖奖品
+ (instancetype)getMbyprobabilityRangeWithArr:(NSArray *)arr {
NSInteger randomNum = arc4random()%100;//控制概率
NSLog(@"randomNum:%@",[NSNumber numberWithDouble:randomNum]);
for (KNTurntableViewModel *obj in arr) {
NSLog(@"obj probabilityRange loc:%@ len %@", [NSNumber numberWithDouble:obj.probabilityRange.location],[NSNumber numberWithDouble:obj.probabilityRange.location+obj.probabilityRange.length]
);
if (randomNum>=obj.probabilityRange.location && randomNum<obj.probabilityRange.location+obj.probabilityRange.length) {//80%的概率 就是0-80
return obj;
}
}
return nil;// 谢谢参与
}
1.3 构造数据模型
- 根据中奖概率probability 确定随机中奖范围probabilityRange
- (KNTurntableViewM *)viewModel{
if(_viewModel == nil){
_viewModel = [KNTurntableViewM new];
NSMutableArray * luckyItemArray = [NSMutableArray array];
double probabilityRangeLoc = 0;
double probabilityRangeLen = 0;
for (int i = 0; i < 6; i++) {//
KNTurntableViewModel *model = [[KNTurntableViewModel alloc] init];
model.title = [NSString stringWithFormat:@"%d-标题",i];
model.index = i;
if(i == 1){
model.probability = 0.5;
}else{
model.probability =0.1;
}
// 初始化probabilityRange
probabilityRangeLoc = probabilityRangeLoc +probabilityRangeLen;
probabilityRangeLen = i+100*model.probability;
//probabilityRange 的计算不要包括谢谢参与的概率
model.probabilityRange = NSMakeRange(probabilityRangeLoc, probabilityRangeLen);
model.imageName = @"qrcode_for_gh";
model.icon = @"https://img-blog.csdnimg.cn/20201114103143654.JPG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTEwMTg5Nzk=,size_16,color_FFFFFF,t_70#pic_center";
[luckyItemArray addObject:model];
}
_viewModel.luckyItemArray = luckyItemArray;
}
return _viewModel ;
}
II、转盘算法
2.1 旋转到指定下标奖品
- 旋转到指定下标奖品
/**
转盘算法
*/
- (void)animationWithSelectonIndex:(NSInteger)index{
[self backToStartPosition];
double perSection = M_PI*2/_luckyItemArray.count;
// //先转4圈 再选区 顺时针(所有这里需要用360-对应的角度) 逆时针不需要
double toValue= ((M_PI*2 - (perSection*index +perSection*0.5)) + M_PI*2*4);
[self RotationWithEndValue: @(toValue - M_PI/2) duration:4 delegate:self];// 因为drawRect从正3点开始画,因此- M_PI/2
}
- (void)RotationWithEndValue:(id)toValue duration:(CFTimeInterval)duration delegate:(id)delegate{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
animation.toValue = toValue;//
animation.duration = duration;
//由快变慢
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];//
animation.delegate = delegate;
[self.layer addAnimation:animation forKey:@"rotation"];
}
- 恢复起始位置
-(void)backToStartPosition{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
animation.toValue = @(0);
animation.duration = 0.001;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[self.layer addAnimation:animation forKey:@"rotation"];
}
2.2 处理旋转结束事件
- CAAnimationDelegate,处理旋转结束事件
#pragma mark - CAAnimationDelegate
- (void)animationDidStart:(CAAnimation *)anim{
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if (self.rotaryEndTurnBlock) {
self.rotaryEndTurnBlock();
}
}
III、iOS 抽奖轮盘边框动画
https://blog.csdn.net/z929118967/article/details/106238484原理:用NSTimer无限替换UIImageView的Image为互为错位的bg_horse_race_lamp_1或者bg_horse_race_lamp_2,达到跑马灯的效果
- 应用场景:iOS 抽奖轮盘边框动画
审核注意事项:1、在抽奖页面添加一句文案“本活动与苹果公司无关” 2、在提交审核时修改分级至17+
3.1 实现代码
//
// ViewController.m
// horse_race_lamp
//
// Created by mac on 2021/4/7.
#import <Masonry/Masonry.h>
#import "ViewController.h"
NSString *const bg_horse_race_lamp_1=@"bg_horse_race_lamp_1";
NSString *const bg_horse_race_lamp_2=@"bg_horse_race_lamp_2";
@interface ViewController ()
/**
用NSTimer无限替换bg_horse_race_lamp_1和bg_horse_race_lamp_2,达到跑马灯的效果
应用场景:iOS 抽奖轮盘边框动画
*/
@property (nonatomic,strong) UIImageView *rotaryTable;
@property (nonatomic,strong) NSTimer *itemBordeTImer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//通过以下两张图片bg_lamp_1 bg_lamp_2,用NSTimer无限替换,达到跑马灯的效果
_rotaryTable = [UIImageView new];
_rotaryTable.tag = 100;
[_rotaryTable setImage:[UIImage imageNamed:bg_horse_race_lamp_1]];
[self.view addSubview:_rotaryTable];
[_rotaryTable mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.offset(0);
}];
_itemBordeTImer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(itemBordeTImerEvent) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_itemBordeTImer forMode:NSRunLoopCommonModes];
}
// 边框动画
- (void)itemBordeTImerEvent
{
if (_rotaryTable.tag == 100) {
_rotaryTable.tag = 101;
[_rotaryTable setImage:[UIImage imageNamed:bg_horse_race_lamp_2]];
}else if (_rotaryTable.tag == 101){
_rotaryTable.tag = 100;
[_rotaryTable setImage:[UIImage imageNamed:bg_horse_race_lamp_1]];
}
}
@end
3.2 从CSDN下载Demo
从CSDN下载Demo:https://download.csdn.net/download/u011018979/16543761
see also
相关文章
- [PHP] laravel框架注意bootstrap/cache
- 《吐血整理》高级系列教程-吃透Fiddler抓包教程(35)-Fiddler如何抓取微信小程序的包-下篇
- 网站在线客服系统源码 | 全渠道在线客服代码下载 (最新版支持外贸商城/H5/小程序/公众号对接)
- 前端vue2+vue-router3+ElementUI+axios综合使用代码教程登录页案例
- 在线客服系统对接微信小程序(客服消息推送)
- 【小程序】同一微信号在微信开发工具上怎么切换小程序
- 【小程序】微信公众号模板消息跳转小程序发送失败:errcode=40013 , errmsg=invalid appid rid:
- 【小程序】微信小程序报错47001 - data format error hint
- 【小程序】微信小程序报错:用户绑定的手机需要进行验证,请在客户端完成短信验证
- 【小程序】微信小程序设置globalData全局数据
- 【小程序】获取手机号报错:getPhoneNumber:fail no permission
- 【小程序】小程序webview不支持打开非业务域名请重新配置
- 【uniapp】uniapp微信小程序开发:启动微信开发者工具提示no such file or directory错误
- 【小程序】uniapp发行微信小程序上传失败Error: Error: {"errCode":-10008,"errMsg":"invalid ip
- 【小程序】如何获取微信小程序代码上传密钥?
- [前端] 前端bootstrap col-xs-6 col-md-3的布局意思
- 解放重复劳动丨华为云IoT API Explorer对接小程序实现系统化应用
- [小程序] 支付宝小程序使用list时提示元素不存在
- [javascript] 支付宝小程序网络GET请求
- [PHP] laravel框架注意bootstrap/cache