前段時間 沒事兒,自己自定義了 一個雷達掃描/擴散效果的View。
掃描View 效果如下:
擴散View 效果如下:
自定義的代碼如下:
1.?RadarView.h
#importtypedef?NS_ENUM(NSInteger,?RadarViewType)?{ ????RadarViewTypeScan, ????RadarViewTypeDiffuse }; @interface?RadarView?:?UIView /**?雷達?空心圓圈的顏色?*/ @property?(nonatomic,?strong)?UIColor?*?radarLineColor; /**?扇形開始顏色?必須由RGBA值初始化 ?*??[UIColor?colorWithRed:?green:?blue:?alpha:] ?*/ @property?(nonatomic,?strong)?UIColor?*?startColor; /**?扇形結(jié)束顏色?必須由RGBA值初始化 ?*??[UIColor?colorWithRed:?green:?blue:?alpha:] ?*/ @property?(nonatomic,?strong)?UIColor?*?endColor; /** ?* ?*??@param?radius???????半徑 ?*??@param?angle????????角度 ?*??@param?radarLineNum?雷達線數(shù)量 ?*??@param?hollowRadius?空心圓半徑 ?* ?*??@return?掃描?雷達?View ?*/ +?(RadarView?*)scanRadarViewWithRadius:(CGFloat)radius ?????????????????????????????????angle:(int)angle ??????????????????????????radarLineNum:(int)radarLineNum ??????????????????????????hollowRadius:(CGFloat)hollowRadius; /** ?* ?*??@param?startRadius?擴散圓?起始的半徑 ?*??@param?endRadius???擴散圓?消失的半徑 ?*??@param?circleColor?擴散圓?的顏色 ?* ?*??@return?擴散?雷達?View ?*/ +?(RadarView?*)diffuseRadarViewWithStartRadius:(CGFloat)startRadius ?????????????????????????????????????endRadius:(CGFloat)endRadius ???????????????????????????????????circleColor:(UIColor?*)circleColor; /** ?*??展示在targerView上 ?* ?*??@param?targerView? ?*/ -?(void)showTargetView:(UIView?*)targerView; -?(void)dismiss; /**?開始掃描動畫?*/ -?(void)startAnimatian; /**?停止掃描動畫?*/ -?(void)stopAnimation; @end
2.?RadarView.m
#import?"RadarView.h" #define?CenterX?self.bounds.size.width*0.5 #define?CenterY?self.bounds.size.height*0.5 #define?DefaultRadarLineColor?[UIColor?colorWithWhite:1?alpha:0.7] #define?DefaultStartColor?[UIColor?colorWithRed:1?green:1?blue:1?alpha:0.5] #define?DefaultEndColor?[UIColor?colorWithRed:1?green:1?blue:1?alpha:0] #define?DefaultCircleColor?[UIColor?colorWithWhite:1?alpha:0.5] @interface?RadarView?() #pragma?mark?-?掃描類型的RadarView?屬性 /**?扇形半徑?*/ @property?(nonatomic,?assign)?CGFloat?sectorRadius; /**?扇形?角度?*/ @property?(nonatomic,?assign)?int?angle; /**?雷達?空心圓圈的數(shù)量?*/ @property?(nonatomic,?assign)?int?radarLineNum; /**?中心?空心圓的半徑?(一般?這里放置一個圓形的頭像)?*/ @property?(nonatomic,?assign)?int?hollowRadius; #pragma?mark?-?擴散類型的RadarView?屬性 /**?擴散動畫?起始?的半徑?*/ @property?(nonatomic,?assign)?CGFloat?startRadius; /**?擴散動畫?結(jié)束?的半徑?*/ @property?(nonatomic,?assign)?CGFloat?endRadius; /**?圓圈的顏色?*/ @property?(nonatomic,?strong)?UIColor?*?circleColor; @property?(nonatomic,?strong)?NSTimer?*?timer; @property?(nonatomic,?assign)?RadarViewType?radarViewType; @end @implementation?RadarView +?(RadarView?*)scanRadarViewWithRadius:(CGFloat)radius?angle:(int)angle?radarLineNum:(int)radarLineNum?hollowRadius:(CGFloat)hollowRadius?{ ????return?[[self?alloc]?initWithRadius:radius?angle:angle?radarLineNum:radarLineNum?hollowRadius:hollowRadius]; } -?(instancetype)initWithRadius:(CGFloat)radius ?????????????????????????angle:(int)angle ??????????????????radarLineNum:(int)radarLineNum ??????????????????hollowRadius:(CGFloat)hollowRadius?{ ????if?(self?=?[super?init])?{ ????????self.radarViewType?=?RadarViewTypeScan; ????????self.sectorRadius?=?radius; ????????self.frame?=?CGRectMake(0,?0,?radius*2,?radius*2); ????????self.angle?=?angle; ????????self.radarLineNum?=?radarLineNum-1; ????????self.hollowRadius?=?hollowRadius; ????????self.backgroundColor?=?[UIColor?clearColor]; ????} ????return?self; } +?(RadarView?*)diffuseRadarViewWithStartRadius:(CGFloat)startRadius?endRadius:(CGFloat)endRadius?circleColor:(UIColor?*)circleColor?{ ????return?[[self?alloc]?initWithStartRadius:startRadius?endRadius:endRadius?circleColor:circleColor]; } -?(instancetype)initWithStartRadius:(CGFloat)startRadius?endRadius:(CGFloat)endRadius?circleColor:(UIColor?*)circleColor?{ ????if?(self?=?[super?init])?{ ????????self.radarViewType?=?RadarViewTypeDiffuse; ????????self.frame?=?CGRectMake(0,?0,?endRadius*2,?endRadius*2); ????????self.startRadius?=?startRadius; ????????self.endRadius?=?endRadius; ????????self.circleColor?=?circleColor; ????????self.backgroundColor?=?[UIColor?clearColor]; ????} ????return?self; } //?Only?override?drawRect:?if?you?perform?custom?drawing. //?An?empty?implementation?adversely?affects?performance?during?animation. -?(void)drawRect:(CGRect)rect?{ ????//?Drawing?code ????if?(_radarViewType?==?RadarViewTypeScan)?{ ????????if?(!_startColor)?{ ????????????_startColor?=?DefaultStartColor; ????????} ????????if?(!_endColor)?{ ????????????_endColor?=?DefaultEndColor; ????????} ????????if?(!_radarLineColor)?{ ????????????_radarLineColor?=?DefaultRadarLineColor; ????????} ???????? ????????//?畫雷達線 ????????[self?drawRadarLine]; ???????? ????????CGContextRef?context?=?UIGraphicsGetCurrentContext(); ????????//?把要畫的扇形?分開畫,一次畫1°,每次的顏色漸變 ????????for?(int?i?=?0;?i?<?_angle;?i++)?{ ????????????UIColor?*?color?=?[self?colorWithCurrentAngleProportion:i*1.0/_angle]; ????????????[self?drawSectorWithContext:context?color:color?startAngle:-90-i]; ????????} ????} } /**?畫扇形?*/ -?(void)drawSectorWithContext:(CGContextRef)context ????????????????????????color:(UIColor?*)color ???????????????????startAngle:(CGFloat)startAngle?{ ????//畫扇形,也就畫圓,只不過是設(shè)置角度的大小,形成一個扇形 ????CGContextSetFillColorWithColor(context,?color.CGColor);//填充顏色 ????CGContextSetLineWidth(context,?0);//線的寬度 ????//以self.radius為半徑圍繞圓心畫指定角度扇形 ????CGContextMoveToPoint(context,?CenterX,?CenterY); ????CGContextAddArc(context,?CenterX,?CenterY,?_sectorRadius,?startAngle?*?M_PI?/?180,?(startAngle-1)?*?M_PI?/?180,?1); ????CGContextClosePath(context); ????CGContextDrawPath(context,?kCGPathFillStroke);?//繪制路徑 } /**?畫雷達線?*/ -?(void)drawRadarLine?{ ????CGFloat?minRadius?=?(_sectorRadius-_hollowRadius)*(pow(0.618,?_radarLineNum-1)); ????/**?畫?圍著空心半徑的第一個空心圓,此圓不在計數(shù)內(nèi)?*/ ????[self?drawLineWithRadius:_hollowRadius+minRadius*0.382]; ???? ????for?(int?i?=?0;?i?<?_radarLineNum;?i++)?{ ????????[self?drawLineWithRadius:_hollowRadius?+?minRadius/pow(0.618,?i)]; ????} } /**?畫空心圓?*/ -?(void)drawLineWithRadius:(CGFloat)radius?{ ????CAShapeLayer?*solidLine?=??[CAShapeLayer?layer]; ????CGMutablePathRef?solidPath?=??CGPathCreateMutable(); ????solidLine.lineWidth?=?1.0f?; ????solidLine.strokeColor?=?_radarLineColor.CGColor; ????solidLine.fillColor?=?[UIColor?clearColor].CGColor; ????CGPathAddEllipseInRect(solidPath,?nil,?CGRectMake(self.bounds.size.width*0.5-radius,?self.bounds.size.height*0.5-radius,?radius*2,?radius*2)); ????solidLine.path?=?solidPath; ????CGPathRelease(solidPath); ????[self.layer?addSublayer:solidLine]; } #pragma?mark?-?展示 -?(void)showTargetView:(UIView?*)targerView?{ ????self.center?=?targerView.center; ????[targerView?addSubview:self]; } #pragma?mark?-? -?(void)dismiss?{ ????[self?removeFromSuperview]; } #pragma?mark?-?開始動畫 -?(void)startAnimatian?{ ????if?(_radarViewType?==?RadarViewTypeScan)?{ ????????CABasicAnimation*?rotationAnimation; ????????rotationAnimation?=?[CABasicAnimation?animationWithKeyPath:@"transform.rotation.z"]; ????????rotationAnimation.toValue?=?[NSNumber?numberWithFloat:?1?*?M_PI?*?2.0?]; ????????rotationAnimation.duration?=?2; ????????rotationAnimation.cumulative?=?YES; ????????rotationAnimation.repeatCount?=?INT_MAX; ????????[self.layer?addAnimation:rotationAnimation?forKey:@"rotationAnimation"]; ????}?else?{ ????????[self?diffuseAnimation]; ????????_timer?=?[NSTimer?scheduledTimerWithTimeInterval:0.5?target:self?selector:@selector(diffuseAnimation)?userInfo:nil?repeats:YES]; ????} } #pragma?mark?-?結(jié)束動畫 -?(void)stopAnimation?{ ????if?(_radarViewType?==?RadarViewTypeScan)?{ ????????[self.layer?removeAnimationForKey:@"rotationAnimation"]; ????}?else?{ ????????[_timer?invalidate]; ????????_timer?=?nil; ????} } -?(UIColor?*)colorWithCurrentAngleProportion:(CGFloat)angleProportion?{ ????NSArray?*?startRGBA?=?[self?RGBA_WithColor:_startColor]; ????NSArray?*?endRGBA?=?[self?RGBA_WithColor:_endColor]; ????CGFloat?currentR?=?[startRGBA[0]?floatValue]?-?([startRGBA[0]?floatValue]-[endRGBA[0]?floatValue])?*?angleProportion; ????CGFloat?currentG?=?[startRGBA[1]?floatValue]?-?([startRGBA[1]?floatValue]-[endRGBA[1]?floatValue])?*?angleProportion; ????CGFloat?currentB?=?[startRGBA[2]?floatValue]?-?([startRGBA[2]?floatValue]-[endRGBA[2]?floatValue])?*?angleProportion; ????CGFloat?currentA?=?[startRGBA[3]?floatValue]?-?([startRGBA[3]?floatValue]-[endRGBA[3]?floatValue])?*?angleProportion; ????return?[UIColor?colorWithRed:currentR?green:currentG?blue:currentB?alpha:currentA]; } /** ?*??將UIColor對象解析成RGBA?值?的數(shù)組 ?* ?*??@param?color?UIColor對象,有RGBA值?初始化的 ?*[UIColor?colorWithRed:rValue?green:gValue?blue:bValue?alpha:aValue] ?* ?*??@return?包含RGBA值得數(shù)組[rValue,?gValue,?bValue,?aValue] ?*/ -?(NSArray?*)RGBA_WithColor:(UIColor?*)color?{ ????NSString?*?colorStr?=?[NSString?stringWithFormat:@"%@",?color]; ????//將RGB值描述分隔成字符串 ????NSArray?*?colorValueArray?=?[colorStr?componentsSeparatedByString:@"?"]; ????NSString?*?R?=?colorValueArray[1]; ????NSString?*?G?=?colorValueArray[2]; ????NSString?*?B?=?colorValueArray[3]; ????NSString?*?A?=?colorValueArray[4]; ????return?@[R,?G,?B,?A]; } /**?畫圓?*/ -?(UIImage?*)drawCircle?{ ????UIGraphicsBeginImageContext(CGSizeMake(_endRadius*2,?_endRadius*2)); ????CGContextRef?context?=?UIGraphicsGetCurrentContext(); ????CGContextMoveToPoint(context,?CenterX,?CenterY); ????CGContextSetFillColorWithColor(context,?_circleColor.CGColor); ????CGContextAddArc(context,?CenterX,?CenterY,?_endRadius,?0,?-2*M_PI,?1); ????CGContextFillPath(context); ????UIImage?*?img?=?UIGraphicsGetImageFromCurrentImageContext(); ????UIGraphicsEndImageContext(); ????return?img; } -?(void)diffuseAnimation?{ ????UIImageView?*?imgView?=?[[UIImageView?alloc]?init]; ????imgView.image?=?[self?drawCircle]; ????imgView.frame?=?CGRectMake(0,?0,?_startRadius,?_startRadius); ????imgView.center?=?CGPointMake(CenterX,?CenterY); ????[self?addSubview:imgView]; ???? ????[UIView?animateWithDuration:2?delay:0?options:UIViewAnimationOptionCurveEaseIn?animations:^{ ????????imgView.frame?=?CGRectMake(0,?0,?_endRadius*2,?_endRadius*2); ????????imgView.center?=?CGPointMake(CenterX,?CenterY); ????????imgView.alpha?=?0; ????}?completion:^(BOOL?finished)?{ ????????[imgView?removeFromSuperview]; ????}]; } @end
3. ViewController.m 中使用的代碼:
#import?"ViewController.h" #import?"RadarView.h" @interface?ViewController?() @property?(nonatomic,?strong)?RadarView?*?scanRadarView; @property?(nonatomic,?strong)?RadarView?*?diffuseRadarView; @end @implementation?ViewController -?(void)viewDidLoad?{ ????[super?viewDidLoad]; ????/**?掃描?類型?RadarView?*/ //????_scanRadarView?=?[RadarView?scanRadarViewWithRadius:self.view.bounds.size.width*0.5?angle:400?radarLineNum:5?hollowRadius:0]; ???? ????/**?擴散?類型?RadarView?*/ ????_diffuseRadarView?=?[RadarView?diffuseRadarViewWithStartRadius:7?endRadius:self.view.bounds.size.width*0.5?circleColor:[UIColor?whiteColor]]; } -?(void)viewDidAppear:(BOOL)animated?{ ????[super?viewDidAppear:animated]; ???? //????[_scanRadarView?showTargetView:self.view]; //????[_scanRadarView?startAnimatian]; ???? ????[_diffuseRadarView?showTargetView:self.view]; ????[_diffuseRadarView?startAnimatian]; } -?(void)didReceiveMemoryWarning?{ ????[super?didReceiveMemoryWarning]; ????//?Dispose?of?any?resources?that?can?be?recreated. } @end
現(xiàn)在定義的是能代碼加載使用,等有空了,再封裝一些方法能在Storyboard中直接使用。