iOS實現雷達掃描效果
本文實例為大傢分享瞭iOS實現雷達掃描的具體代碼,供大傢參考,具體內容如下
#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
.m文件
// // 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; }
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。