GALCaptcha.m 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. //
  2. // GALCaptcha.m
  3. // shiku_im
  4. //
  5. // Created by JayLuo on 2020/1/14.
  6. // Copyright © 2020 Reese. All rights reserved.
  7. //
  8. #import "GALCaptcha.h"
  9. #define kRandomColor [UIColor colorWithRed:arc4random() % 256 / 256.0 green:arc4random() % 256 / 256.0 blue:arc4random() % 256 / 256.0 alpha:1.0];
  10. #define kLineCount 6 //干扰线条数
  11. #define kLineWidth 1.0 //线宽
  12. #define kCharCount 4 //字符个数
  13. #define kFontSize [UIFont systemFontOfSize:arc4random() % 5 + 15]
  14. @implementation GALCaptcha
  15. -(instancetype)initWithFrame:(CGRect)frame
  16. {
  17. if (self = [super initWithFrame:frame]) {
  18. self.layer.cornerRadius = 5.0;
  19. self.layer.masksToBounds = YES;
  20. self.backgroundColor = [UIColor greenColor];
  21. //显示一个随机验证码
  22. [self showCaptcha];
  23. }
  24. return self;
  25. }
  26. - (void)refresh {
  27. //点击界面,切换验证码
  28. [self showCaptcha];
  29. //setNeedsDisplay调用drawRect方法来实现view的绘制
  30. [self setNeedsDisplay];
  31. }
  32. -(void)showCaptcha
  33. {
  34. //从字符数组中随机抽取相应数量的字符,组成验证码字符串
  35. //数组中存放的是全部可选的字符,可以是字母,也可以是中文
  36. self.CatArray = [[NSArray alloc] initWithObjects:@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"A",@"B",@"C",@"D",@"E",@"F",@"G",@"H",@"I",@"J",@"K",@"L",@"M",@"N",@"O",@"P",@"Q",@"R",@"S",@"T",@"U",@"V",@"W",@"X",@"Y",@"Z",@"a",@"b",@"c",@"d",@"e",@"f",@"g",@"h",@"i",@"j",@"k",@"l",@"m",@"n",@"o",@"p",@"q",@"r",@"s",@"t",@"u",@"v",@"w",@"x",@"y",@"z",nil];
  37. //如果能确定最大需要的容量,使用initWithCapacity:来设置,好处是当元素个数不超过容量时,添加元素不需要重新分配内存
  38. NSMutableString *getStr = [[NSMutableString alloc] initWithCapacity:kCharCount];
  39. self.CatString = [[NSMutableString alloc] initWithCapacity:kCharCount];
  40. //随机从数组中选取需要个数的字符,然后拼接为一个字符串
  41. for(int i = 0; i < kCharCount; i++)
  42. {
  43. NSInteger index = arc4random() % ([self.CatArray count] - 1);
  44. getStr = [self.CatArray objectAtIndex:index];
  45. self.CatString = (NSMutableString *)[self.CatString stringByAppendingString:getStr];
  46. }
  47. }
  48. #pragma mark 点击view时调用,因为当前类自身就是UIView,点击更换验证码可以直接写到这个方法中,不用再额外添加手势
  49. -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  50. {
  51. //点击界面,切换验证码
  52. [self showCaptcha];
  53. //setNeedsDisplay调用drawRect方法来实现view的绘制
  54. [self setNeedsDisplay];
  55. }
  56. #pragma mark 绘制界面(1.UIView初始化后自动调用; 2.调用setNeedsDisplay方法时会自动调用)
  57. - (void)drawRect:(CGRect)rect {
  58. // 重写父类方法,首先要调用父类的方法
  59. [super drawRect:rect];
  60. //设置随机背景颜色
  61. self.backgroundColor = kRandomColor;
  62. //获得要显示验证码字符串,根据长度,计算每个字符显示的大概位置
  63. NSString *text = [NSString stringWithFormat:@"%@",self.CatString];
  64. CGSize cSize = [@"S" sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:20]}]; int width = rect.size.width / text.length - cSize.width;
  65. int height = rect.size.height - cSize.height;
  66. CGPoint point;
  67. //依次绘制每一个字符,可以设置显示的每个字符的字体大小、颜色、样式等
  68. float pX, pY;
  69. for (int i = 0; i < text.length; i++)
  70. {
  71. pX = arc4random() % width + rect.size.width / text.length * i;
  72. pY = arc4random() % height;
  73. point = CGPointMake(pX, pY);
  74. unichar c = [text characterAtIndex:i];
  75. NSString *textC = [NSString stringWithFormat:@"%C", c];
  76. [textC drawAtPoint:point withAttributes:@{NSFontAttributeName:kFontSize}];
  77. }
  78. //调用drawRect:之前,系统会向栈中压入一个CGContextRef,调用UIGraphicsGetCurrentContext()会取栈顶的CGContextRef
  79. CGContextRef context = UIGraphicsGetCurrentContext();
  80. //设置画线宽度
  81. CGContextSetLineWidth(context, kLineWidth);
  82. //绘制干扰的彩色直线
  83. for(int i = 0; i < kLineCount; i++)
  84. {
  85. //设置线的随机颜色
  86. UIColor *color = kRandomColor;
  87. CGContextSetStrokeColorWithColor(context, [color CGColor]);
  88. //设置线的起点
  89. pX = arc4random() % (int)rect.size.width;
  90. pY = arc4random() % (int)rect.size.height;
  91. CGContextMoveToPoint(context, pX, pY);
  92. //设置线终点
  93. pX = arc4random() % (int)rect.size.width;
  94. pY = arc4random() % (int)rect.size.height;
  95. CGContextAddLineToPoint(context, pX, pY);
  96. // //设置线条起点和终点的样式为圆角
  97. // CGContextSetLineCap(context, kCGLineCapRound);
  98. // //设置线条的转角的样式为圆角
  99. // CGContextSetLineJoin(context, kCGLineJoinRound);
  100. //画线
  101. CGContextStrokePath(context);
  102. }
  103. }
  104. @end