- #import <UIKit/UIKit.h>
-
- @interface LTIndicatiorView : UIView
- @property(nonatomic,strong)UIColor *color;
- @property(nonatomic,assign)float repeatCount;
- @property(nonatomic,strong)UIColor *borderColor;
- @property(nonatomic,assign)float borderWidth;
- @end
-
- @interface LTRadarView : UIView
- @property(nonatomic,strong)UIColor *color;
- @property(nonatomic,strong)UIColor *borderColor;
- @property(nonatomic,assign)float borderWidth;
- @property(nonatomic,assign)int pulsingCount;
- @property(nonatomic,assign)float duration;
- @property(nonatomic,assign)float repeatCount;
- @property(nonatomic,strong)CALayer *pulsingLayer;
-
-
- @end
- //
- // LTRadarView.m
- // raderScan
- //
- // Created by mac on 17/2/5.
- // Copyright © 2017年 mac. All rights reserved.
- //
-
- #import "LTRadarView.h"
-
- #define Angel 15
-
- @interface LTRadarButton : UIButton
-
- @end
-
- @implementation LTRadarButton
-
- - (void)removeFromSuperview
- {
- [UIView beginAnimations:@"" context:nil];
- [UIView setAnimationDuration:0.5];
- self.transform = CGAffineTransformMakeScale(0.2, 0.2);
- self.alpha = 0;
- [UIView setAnimationDidStopSelector:@selector(callSuperRemoveFromSuperview)];
- [UIView commitAnimations];
-
- }
-
- - (void)callSuperRemoveFromSuperview
- {
- [super removeFromSuperview];
- }
-
- - (id)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- self.alpha = 0;
- return self;
- }
-
- - (void)didMoveToWindow
- {
- [super didMoveToWindow];
- self.transform = CGAffineTransformMakeScale(0.2, 0.2);
- if (self.window) {
- [UIView animateWithDuration:0.5 animations:^{
- self.transform = CGAffineTransformIdentity;
- self.alpha = 1;
- }];
- }
-
- }
-
-
-
- @end
-
-
- @implementation LTIndicatiorView
-
- - (id)initWithFrame:(CGRect)frame
- {
- if (self = [super initWithFrame:frame]) {
- _color = [UIColor greenColor];
- _repeatCount = HUGE_VALF;
- _borderColor = [UIColor redColor];
- _borderWidth = 1.0f;
- }
- return self;
- }
-
-
- // Only override drawRect: if you perform custom drawing.
- // An empty implementation adversely affects performance during animation.
- - (void)drawRect:(CGRect)rect {
- // Drawing code
-
- self.backgroundColor = [UIColor whiteColor];
- [super drawRect:rect];
- self.layer.cornerRadius = self.frame.size.height/2.0f;
- self.clipsToBounds = YES;
- self.layer.borderColor = [UIColor clearColor].CGColor;
- self.layer.borderWidth = 50;
- self.layer.masksToBounds = YES;
-
-
- CGContextRef context = UIGraphicsGetCurrentContext();
- for (int i = 0; i < Angel; i++) {
- CGFloat alpha = (float)i /(float)600;
- CGColorRef shadowColor = [[UIColor greenColor] colorWithAlphaComponent:alpha].CGColor;//计算扇形填充颜色
- CGContextSetFillColorWithColor(context, shadowColor);
- CGContextMoveToPoint(context, self.center.x, self.center.y);//指定员心
- CGFloat startAngle = (-Angel+i+1.15)/Angel*(float)M_PI;
- CGFloat endAngle = (-Angel+i-1.15)/Angel*(float)M_PI;
- // NSLog(@"startAngle = %f endAngle = %f ,alpha = %f",startAngle,endAngle,alpha);
- CGContextAddArc(context, self.center.x, self.center.y, self.frame.size.height/2.0f,0, 25, 1);//画一个扇形
- CGContextClosePath(context);
-
- CGContextDrawPath(context, kCGPathFill);//绘制扇形
-
- }
-
- CGContextSetLineWidth(context, 1);//扫描线宽度
- CGContextSetStrokeColorWithColor(context, [_color colorWithAlphaComponent:1].CGColor);//扫描线颜色
- CGContextMoveToPoint(context, self.center.x, self.center.y);
- CGContextAddLineToPoint(context, self.frame.size.height, self.center.y);
- CGContextStrokePath(context);
-
- CGContextSetRGBStrokeColor(context,255/255.0, 255/255.0, 255/255.0, 0.1);//最外面圆颜色
- CGContextSetLineWidth(context, 10);//线宽度
- CGContextAddArc(context, self.center.x, self.center.y, self.frame.size.height/2.0, 0, 2*M_PI, 1);//添加一个圆
- CGContextDrawPath(context, kCGPathStroke);//绘制路径
-
- CGContextStrokePath(context);//显示绘制
-
-
- //扫描动画
- CABasicAnimation *rotateAnimation = [CABasicAnimation animation];
- rotateAnimation.keyPath = @"transform.rotation.z";
- rotateAnimation.toValue = @(2*M_PI);
- rotateAnimation.duration = 3;
- rotateAnimation.removedOnCompletion = NO;
- rotateAnimation.repeatCount = _repeatCount;
-
- [self.layer addAnimation:rotateAnimation forKey:@"rotate_layer"];
- }
-
-
- @end
-
-
- @implementation LTRadarView
- {
- NSMutableArray *items;
- }
-
-
- - (id)initWithFrame:(CGRect)frame
- {
- if (self = [super initWithFrame:frame]) {
-
- items = [NSMutableArray array];
- _color = [UIColor redColor];
-
- _borderColor = [UIColor greenColor];
- _pulsingCount = 3;
- _duration = 3;
- _repeatCount = HUGE_VALF;
- _borderWidth = 3.0f;
- }
- return self;
- }
-
- // Only override drawRect: if you perform custom drawing.
- // An empty implementation adversely affects performance during animation.
- - (void)drawRect:(CGRect)rect {
- // Drawing code
- [super drawRect:rect];
-
- self.layer.cornerRadius = self.frame.size.height/2;
- self.clipsToBounds = YES;
- self.layer.borderColor = [UIColor clearColor].CGColor;
- self.layer.borderColor = [UIColor clearColor].CGColor;
- self.layer.borderWidth = 50;
- self.layer.masksToBounds = YES;
-
- CGContextRef ctx = UIGraphicsGetCurrentContext();
- CGContextSetRGBFillColor(ctx, 0/255.0, 0/255.0, 0/255.0, 1);//圆颜色
- CGContextSetLineWidth(ctx, 1);//宽度
- CGContextAddArc(ctx, self.center.x, self.center.y, self.frame.size.height/2, 0, 2*M_PI, 1);//添加一个圆
- CGContextDrawPath(ctx, kCGPathStroke);//绘制
- CGContextStrokePath(ctx);//显示
-
- CALayer *animationLayer = [CALayer layer];
- animationLayer.frame = self.layer.frame;
- for (int i = 0; i < _pulsingCount; i++) {
-
- CALayer *pulsingLayer = [CALayer layer];
- pulsingLayer.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
- pulsingLayer.borderColor = [UIColor clearColor].CGColor;
- pulsingLayer.borderWidth = 1;
- pulsingLayer.cornerRadius = rect.size.height/2;
- pulsingLayer.backgroundColor = [UIColor redColor].CGColor;
-
- CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
- animationGroup.fillMode = kCAFillModeBoth;
- animationGroup.beginTime = CACurrentMediaTime() + (float) i * _duration / _pulsingCount;
- animationGroup.duration = _duration;
- animationGroup.repeatCount = HUGE_VALF;
- animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
- animationGroup.autoreverses = NO;
- animationGroup.delegate = self;
- animationGroup.removedOnCompletion = NO;
-
- CABasicAnimation *scaleAnimation = [CABasicAnimation animation];
- scaleAnimation.keyPath = @"transform.scale";
- scaleAnimation.removedOnCompletion = NO;
- scaleAnimation.fromValue = @(0.0f);
- scaleAnimation.toValue = @1.0f;
- scaleAnimation.autoreverses = NO;
-
-
- CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animation];
- opacityAnimation.keyPath = @"opacity";
- opacityAnimation.values = @[@1.0,@0.75,@0.5,@0.25,@0.0];
- opacityAnimation.keyTimes = @[@0.0,@0.25,@0.5,@0.75,@1];
- opacityAnimation.autoreverses = NO;
- opacityAnimation.removedOnCompletion = NO;
-
- animationGroup.animations = @[scaleAnimation,opacityAnimation];
- [pulsingLayer addAnimation:animationGroup forKey:@"pulsing"];
-
- [animationLayer addSublayer:pulsingLayer];
- }
-
- [self.layer addSublayer:animationLayer];
-
- [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(addOrReplaceItem) userInfo:nil repeats:YES];
- }
-
-
- - (void)animation:(CALayer *)layer
- {
- CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
- animationGroup.fillMode = kCAFillModeBoth;
- animationGroup.beginTime = CACurrentMediaTime() + 1 * _duration / _pulsingCount;
- animationGroup.duration = _duration;
- animationGroup.repeatCount = HUGE_VALF;
- animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
- animationGroup.autoreverses = NO;
- animationGroup.delegate = self;
- animationGroup.removedOnCompletion = NO;
-
- CABasicAnimation *scaleAnimation = [CABasicAnimation animation];
- scaleAnimation.keyPath = @"transform.scale";
- scaleAnimation.removedOnCompletion = NO;
- scaleAnimation.fromValue = @(0.0f);
- scaleAnimation.toValue = @1.0f;
- scaleAnimation.autoreverses = NO;
-
-
- CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animation];
- opacityAnimation.keyPath = @"opacity";
- opacityAnimation.values = @[@1.0,@0.75,@0.5,@0.25,@0.0];
- opacityAnimation.keyTimes = @[@0.0,@0.25,@0.5,@0.75,@1];
- opacityAnimation.autoreverses = NO;
- opacityAnimation.removedOnCompletion = NO;
-
- animationGroup.animations = @[scaleAnimation,opacityAnimation];
- [layer addAnimation:animationGroup forKey:@"pulsing"];
-
-
- }
-
- #define RandomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0]
- /*
- 生成一个在圆里面的坐标
- 生成的坐标要围绕中心的绿点(圆心),让我们重新翻开数学课本,看看高中数学对三角函数的定义:
- 在一个平面直角坐标系中,以原点为圆心,1 为半径画一个圆,这个圆交 x 轴于 A 点。以 O 为旋转中心,将 A 点逆时针旋转一定的角度α至 B 点,设此时 B 点的坐标是(x,y),那么此时 y 的值就叫做α的正弦,记作 sinα;此时 x 的值就叫做α的余弦,记作 cosα;y 与 x 的比值 y/x 就叫做α的正切,记作 tanα。
-
- 任意角三角函数 正弦sinθ=y/r, 余弦cosθ=x/r,正切tanθ=y/x,余切cotθ=x/y,正割secθ=r/x,余割cscθ=r/y
- 锐角三角函数 正弦sinA=a/c, 余弦cosA=b/c,正切tanA=a/b,余切cotA=b/a,正割secA=c/b,余割cscA=c/a
-
- 还有一个很重要的公式:圆的参数方程:以点O(a,b)为圆心,以r为半径的圆的参数方程是 x=a+r*cosθ, y=b+r*sinθ, (其中θ为参数)
- 到这里为止,思路就清晰了,以下是generateCenterPointInRadar的方法实现:
- */
-
- - (CGPoint)generateCenterPointInRadar
- {
- float angle = arc4random() % 360;//随机一个角度
- float radius = arc4random() % (int)((self.bounds.size.width - 44)/2);//随机一个半径, 这里减去44是因为要把这个view显示在圆里面,如果不减44,则有可能会显示在圓外面
- double x = cos(angle) * radius;//计算随机出现的一个角度的x坐标 x=a+r*cosθ r = radius, θ = angle ,a = 圆心的x坐标
- double y = sin(angle) * radius;//计算随机出现的一个角度的y坐标 y=b+r*sinθ r = radius, θ = angle ,b = 圆心的y坐标
- return CGPointMake(x + self.bounds.size.width / 2, y + self.bounds.size.height / 2);//x y 分别加个圆心的坐标即self.center.x.y
- }
-
- - (void)addOrReplaceItem
- {
- int maxCount = 10;
-
- LTRadarButton *radarButton = [LTRadarButton buttonWithType:UIButtonTypeCustom];
- radarButton.frame = CGRectMake(0, 0, 44, 44);
- radarButton.backgroundColor = RandomColor;
- radarButton.layer.cornerRadius = 44/2;
-
-
- do {
- CGPoint center = [self generateCenterPointInRadar];
- radarButton.center = CGPointMake(center.x, center.y);
- } while ([self itemFrameIntersectsInOtherItem:radarButton.frame]);
-
-
- [self addSubview:radarButton];
- [items addObject:radarButton];
-
- if (items.count > maxCount)
- {
- UIView * view = [items firstObject];
- [view removeFromSuperview];
- [items removeObject:view];
- }
- }
-
-
- /*
- 我们现在在生成每个item的center的时候,没有和已有的item进行比较,这是一个比较耗性能的操作,如果你的itemSize过大,maxCount过多,这甚至能导致死循环,如果是那样的话,你可能在对itemSize以及maxCount做出限制的同时,也对循环的数量也进行控制,如果在生成一个item的center的时候,进行了过多的循环,就可以视为进入死循环了,在这种情况下,你只能重新计算已有的centers。这里不考虑这种极端情况,因为目前的itemSize和maxCount的配合,不会出现死循环。
- 我们添加一个itemFrameIntersectsInOtherItem私有方法来判断是否和之前生成的center有了重叠:
- */
- - (BOOL)itemFrameIntersectsInOtherItem:(CGRect)frame
- {
- for (UIView *item in items)
- {
- if (CGRectIntersectsRect(item.frame, frame))
- {
- return YES;
- }
- }
- return NO;
- }