经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » iOS » 查看文章
iOS实现雷达扫描效果
来源:jb51  时间:2021/10/11 9:22:39  对本文有异议

本文实例为大家分享了iOS实现雷达扫描的具体代码,供大家参考,具体内容如下

  1. #import <UIKit/UIKit.h>
  2. @interface LTIndicatiorView : UIView
  3. @property(nonatomic,strong)UIColor *color;
  4. @property(nonatomic,assign)float repeatCount;
  5. @property(nonatomic,strong)UIColor *borderColor;
  6. @property(nonatomic,assign)float borderWidth;
  7. @end
  8. @interface LTRadarView : UIView
  9. @property(nonatomic,strong)UIColor *color;
  10. @property(nonatomic,strong)UIColor *borderColor;
  11. @property(nonatomic,assign)float borderWidth;
  12. @property(nonatomic,assign)int pulsingCount;
  13. @property(nonatomic,assign)float duration;
  14. @property(nonatomic,assign)float repeatCount;
  15. @property(nonatomic,strong)CALayer *pulsingLayer;
  16. @end

.m文件

  1. //
  2. // LTRadarView.m
  3. // raderScan
  4. //
  5. // Created by mac on 17/2/5.
  6. // Copyright © 2017年 mac. All rights reserved.
  7. //
  8. #import "LTRadarView.h"
  9. #define Angel 15
  10. @interface LTRadarButton : UIButton
  11. @end
  12. @implementation LTRadarButton
  13. - (void)removeFromSuperview
  14. {
  15. [UIView beginAnimations:@"" context:nil];
  16. [UIView setAnimationDuration:0.5];
  17. self.transform = CGAffineTransformMakeScale(0.2, 0.2);
  18. self.alpha = 0;
  19. [UIView setAnimationDidStopSelector:@selector(callSuperRemoveFromSuperview)];
  20. [UIView commitAnimations];
  21. }
  22. - (void)callSuperRemoveFromSuperview
  23. {
  24. [super removeFromSuperview];
  25. }
  26. - (id)initWithFrame:(CGRect)frame
  27. {
  28. self = [super initWithFrame:frame];
  29. self.alpha = 0;
  30. return self;
  31. }
  32. - (void)didMoveToWindow
  33. {
  34. [super didMoveToWindow];
  35. self.transform = CGAffineTransformMakeScale(0.2, 0.2);
  36. if (self.window) {
  37. [UIView animateWithDuration:0.5 animations:^{
  38. self.transform = CGAffineTransformIdentity;
  39. self.alpha = 1;
  40. }];
  41. }
  42. }
  43. @end
  44. @implementation LTIndicatiorView
  45. - (id)initWithFrame:(CGRect)frame
  46. {
  47. if (self = [super initWithFrame:frame]) {
  48. _color = [UIColor greenColor];
  49. _repeatCount = HUGE_VALF;
  50. _borderColor = [UIColor redColor];
  51. _borderWidth = 1.0f;
  52. }
  53. return self;
  54. }
  55. // Only override drawRect: if you perform custom drawing.
  56. // An empty implementation adversely affects performance during animation.
  57. - (void)drawRect:(CGRect)rect {
  58. // Drawing code
  59. self.backgroundColor = [UIColor whiteColor];
  60. [super drawRect:rect];
  61. self.layer.cornerRadius = self.frame.size.height/2.0f;
  62. self.clipsToBounds = YES;
  63. self.layer.borderColor = [UIColor clearColor].CGColor;
  64. self.layer.borderWidth = 50;
  65. self.layer.masksToBounds = YES;
  66. CGContextRef context = UIGraphicsGetCurrentContext();
  67. for (int i = 0; i < Angel; i++) {
  68. CGFloat alpha = (float)i /(float)600;
  69. CGColorRef shadowColor = [[UIColor greenColor] colorWithAlphaComponent:alpha].CGColor;//计算扇形填充颜色
  70. CGContextSetFillColorWithColor(context, shadowColor);
  71. CGContextMoveToPoint(context, self.center.x, self.center.y);//指定员心
  72. CGFloat startAngle = (-Angel+i+1.15)/Angel*(float)M_PI;
  73. CGFloat endAngle = (-Angel+i-1.15)/Angel*(float)M_PI;
  74. // NSLog(@"startAngle = %f endAngle = %f ,alpha = %f",startAngle,endAngle,alpha);
  75. CGContextAddArc(context, self.center.x, self.center.y, self.frame.size.height/2.0f,0, 25, 1);//画一个扇形
  76. CGContextClosePath(context);
  77. CGContextDrawPath(context, kCGPathFill);//绘制扇形
  78. }
  79. CGContextSetLineWidth(context, 1);//扫描线宽度
  80. CGContextSetStrokeColorWithColor(context, [_color colorWithAlphaComponent:1].CGColor);//扫描线颜色
  81. CGContextMoveToPoint(context, self.center.x, self.center.y);
  82. CGContextAddLineToPoint(context, self.frame.size.height, self.center.y);
  83. CGContextStrokePath(context);
  84. CGContextSetRGBStrokeColor(context,255/255.0, 255/255.0, 255/255.0, 0.1);//最外面圆颜色
  85. CGContextSetLineWidth(context, 10);//线宽度
  86. CGContextAddArc(context, self.center.x, self.center.y, self.frame.size.height/2.0, 0, 2*M_PI, 1);//添加一个圆
  87. CGContextDrawPath(context, kCGPathStroke);//绘制路径
  88. CGContextStrokePath(context);//显示绘制
  89. //扫描动画
  90. CABasicAnimation *rotateAnimation = [CABasicAnimation animation];
  91. rotateAnimation.keyPath = @"transform.rotation.z";
  92. rotateAnimation.toValue = @(2*M_PI);
  93. rotateAnimation.duration = 3;
  94. rotateAnimation.removedOnCompletion = NO;
  95. rotateAnimation.repeatCount = _repeatCount;
  96. [self.layer addAnimation:rotateAnimation forKey:@"rotate_layer"];
  97. }
  98. @end
  99. @implementation LTRadarView
  100. {
  101. NSMutableArray *items;
  102. }
  103. - (id)initWithFrame:(CGRect)frame
  104. {
  105. if (self = [super initWithFrame:frame]) {
  106. items = [NSMutableArray array];
  107. _color = [UIColor redColor];
  108. _borderColor = [UIColor greenColor];
  109. _pulsingCount = 3;
  110. _duration = 3;
  111. _repeatCount = HUGE_VALF;
  112. _borderWidth = 3.0f;
  113. }
  114. return self;
  115. }
  116. // Only override drawRect: if you perform custom drawing.
  117. // An empty implementation adversely affects performance during animation.
  118. - (void)drawRect:(CGRect)rect {
  119. // Drawing code
  120. [super drawRect:rect];
  121. self.layer.cornerRadius = self.frame.size.height/2;
  122. self.clipsToBounds = YES;
  123. self.layer.borderColor = [UIColor clearColor].CGColor;
  124. self.layer.borderColor = [UIColor clearColor].CGColor;
  125. self.layer.borderWidth = 50;
  126. self.layer.masksToBounds = YES;
  127. CGContextRef ctx = UIGraphicsGetCurrentContext();
  128. CGContextSetRGBFillColor(ctx, 0/255.0, 0/255.0, 0/255.0, 1);//圆颜色
  129. CGContextSetLineWidth(ctx, 1);//宽度
  130. CGContextAddArc(ctx, self.center.x, self.center.y, self.frame.size.height/2, 0, 2*M_PI, 1);//添加一个圆
  131. CGContextDrawPath(ctx, kCGPathStroke);//绘制
  132. CGContextStrokePath(ctx);//显示
  133. CALayer *animationLayer = [CALayer layer];
  134. animationLayer.frame = self.layer.frame;
  135. for (int i = 0; i < _pulsingCount; i++) {
  136. CALayer *pulsingLayer = [CALayer layer];
  137. pulsingLayer.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
  138. pulsingLayer.borderColor = [UIColor clearColor].CGColor;
  139. pulsingLayer.borderWidth = 1;
  140. pulsingLayer.cornerRadius = rect.size.height/2;
  141. pulsingLayer.backgroundColor = [UIColor redColor].CGColor;
  142. CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
  143. animationGroup.fillMode = kCAFillModeBoth;
  144. animationGroup.beginTime = CACurrentMediaTime() + (float) i * _duration / _pulsingCount;
  145. animationGroup.duration = _duration;
  146. animationGroup.repeatCount = HUGE_VALF;
  147. animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
  148. animationGroup.autoreverses = NO;
  149. animationGroup.delegate = self;
  150. animationGroup.removedOnCompletion = NO;
  151. CABasicAnimation *scaleAnimation = [CABasicAnimation animation];
  152. scaleAnimation.keyPath = @"transform.scale";
  153. scaleAnimation.removedOnCompletion = NO;
  154. scaleAnimation.fromValue = @(0.0f);
  155. scaleAnimation.toValue = @1.0f;
  156. scaleAnimation.autoreverses = NO;
  157. CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animation];
  158. opacityAnimation.keyPath = @"opacity";
  159. opacityAnimation.values = @[@1.0,@0.75,@0.5,@0.25,@0.0];
  160. opacityAnimation.keyTimes = @[@0.0,@0.25,@0.5,@0.75,@1];
  161. opacityAnimation.autoreverses = NO;
  162. opacityAnimation.removedOnCompletion = NO;
  163. animationGroup.animations = @[scaleAnimation,opacityAnimation];
  164. [pulsingLayer addAnimation:animationGroup forKey:@"pulsing"];
  165. [animationLayer addSublayer:pulsingLayer];
  166. }
  167. [self.layer addSublayer:animationLayer];
  168. [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(addOrReplaceItem) userInfo:nil repeats:YES];
  169. }
  170. - (void)animation:(CALayer *)layer
  171. {
  172. CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
  173. animationGroup.fillMode = kCAFillModeBoth;
  174. animationGroup.beginTime = CACurrentMediaTime() + 1 * _duration / _pulsingCount;
  175. animationGroup.duration = _duration;
  176. animationGroup.repeatCount = HUGE_VALF;
  177. animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
  178. animationGroup.autoreverses = NO;
  179. animationGroup.delegate = self;
  180. animationGroup.removedOnCompletion = NO;
  181. CABasicAnimation *scaleAnimation = [CABasicAnimation animation];
  182. scaleAnimation.keyPath = @"transform.scale";
  183. scaleAnimation.removedOnCompletion = NO;
  184. scaleAnimation.fromValue = @(0.0f);
  185. scaleAnimation.toValue = @1.0f;
  186. scaleAnimation.autoreverses = NO;
  187. CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animation];
  188. opacityAnimation.keyPath = @"opacity";
  189. opacityAnimation.values = @[@1.0,@0.75,@0.5,@0.25,@0.0];
  190. opacityAnimation.keyTimes = @[@0.0,@0.25,@0.5,@0.75,@1];
  191. opacityAnimation.autoreverses = NO;
  192. opacityAnimation.removedOnCompletion = NO;
  193. animationGroup.animations = @[scaleAnimation,opacityAnimation];
  194. [layer addAnimation:animationGroup forKey:@"pulsing"];
  195. }
  196. #define RandomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0]
  197. /*
  198. 生成一个在圆里面的坐标
  199. 生成的坐标要围绕中心的绿点(圆心),让我们重新翻开数学课本,看看高中数学对三角函数的定义:
  200. 在一个平面直角坐标系中,以原点为圆心,1 为半径画一个圆,这个圆交 x 轴于 A 点。以 O 为旋转中心,将 A 点逆时针旋转一定的角度α至 B 点,设此时 B 点的坐标是(x,y),那么此时 y 的值就叫做α的正弦,记作 sinα;此时 x 的值就叫做α的余弦,记作 cosα;y 与 x 的比值 y/x 就叫做α的正切,记作 tanα。
  201. 任意角三角函数 正弦sinθ=y/r, 余弦cosθ=x/r,正切tanθ=y/x,余切cotθ=x/y,正割secθ=r/x,余割cscθ=r/y
  202. 锐角三角函数 正弦sinA=a/c, 余弦cosA=b/c,正切tanA=a/b,余切cotA=b/a,正割secA=c/b,余割cscA=c/a
  203. 还有一个很重要的公式:圆的参数方程:以点O(a,b)为圆心,以r为半径的圆的参数方程是 x=a+r*cosθ, y=b+r*sinθ, (其中θ为参数)
  204. 到这里为止,思路就清晰了,以下是generateCenterPointInRadar的方法实现:
  205. */
  206. - (CGPoint)generateCenterPointInRadar
  207. {
  208. float angle = arc4random() % 360;//随机一个角度
  209. float radius = arc4random() % (int)((self.bounds.size.width - 44)/2);//随机一个半径, 这里减去44是因为要把这个view显示在圆里面,如果不减44,则有可能会显示在圓外面
  210. double x = cos(angle) * radius;//计算随机出现的一个角度的x坐标 x=a+r*cosθ r = radius, θ = angle ,a = 圆心的x坐标
  211. double y = sin(angle) * radius;//计算随机出现的一个角度的y坐标 y=b+r*sinθ r = radius, θ = angle ,b = 圆心的y坐标
  212. return CGPointMake(x + self.bounds.size.width / 2, y + self.bounds.size.height / 2);//x y 分别加个圆心的坐标即self.center.x.y
  213. }
  214. - (void)addOrReplaceItem
  215. {
  216. int maxCount = 10;
  217. LTRadarButton *radarButton = [LTRadarButton buttonWithType:UIButtonTypeCustom];
  218. radarButton.frame = CGRectMake(0, 0, 44, 44);
  219. radarButton.backgroundColor = RandomColor;
  220. radarButton.layer.cornerRadius = 44/2;
  221. do {
  222. CGPoint center = [self generateCenterPointInRadar];
  223. radarButton.center = CGPointMake(center.x, center.y);
  224. } while ([self itemFrameIntersectsInOtherItem:radarButton.frame]);
  225. [self addSubview:radarButton];
  226. [items addObject:radarButton];
  227. if (items.count > maxCount)
  228. {
  229. UIView * view = [items firstObject];
  230. [view removeFromSuperview];
  231. [items removeObject:view];
  232. }
  233. }
  234. /*
  235. 我们现在在生成每个item的center的时候,没有和已有的item进行比较,这是一个比较耗性能的操作,如果你的itemSize过大,maxCount过多,这甚至能导致死循环,如果是那样的话,你可能在对itemSize以及maxCount做出限制的同时,也对循环的数量也进行控制,如果在生成一个item的center的时候,进行了过多的循环,就可以视为进入死循环了,在这种情况下,你只能重新计算已有的centers。这里不考虑这种极端情况,因为目前的itemSize和maxCount的配合,不会出现死循环。
  236. 我们添加一个itemFrameIntersectsInOtherItem私有方法来判断是否和之前生成的center有了重叠:
  237. */
  238. - (BOOL)itemFrameIntersectsInOtherItem:(CGRect)frame
  239. {
  240. for (UIView *item in items)
  241. {
  242. if (CGRectIntersectsRect(item.frame, frame))
  243. {
  244. return YES;
  245. }
  246. }
  247. return NO;
  248. }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号