iOS 自定義雷達(dá) 掃描/擴(kuò)散動(dòng)畫 View
前段時(shí)間 沒事兒,自己自定義了 一個(gè)雷達(dá)掃描/擴(kuò)散效果的View。
掃描View 效果如下:
擴(kuò)散View 效果如下:
自定義的代碼如下:
1.?RadarView.h
#importtypedef?NS_ENUM(NSInteger,?RadarViewType)?{
????RadarViewTypeScan,
????RadarViewTypeDiffuse
};
@interface?RadarView?:?UIView
/**?雷達(dá)?空心圓圈的顏色?*/
@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?雷達(dá)線數(shù)量
?*??@param?hollowRadius?空心圓半徑
?*
?*??@return?掃描?雷達(dá)?View
?*/
+?(RadarView?*)scanRadarViewWithRadius:(CGFloat)radius
?????????????????????????????????angle:(int)angle
??????????????????????????radarLineNum:(int)radarLineNum
??????????????????????????hollowRadius:(CGFloat)hollowRadius;
/**
?*
?*??@param?startRadius?擴(kuò)散圓?起始的半徑
?*??@param?endRadius???擴(kuò)散圓?消失的半徑
?*??@param?circleColor?擴(kuò)散圓?的顏色
?*
?*??@return?擴(kuò)散?雷達(dá)?View
?*/
+?(RadarView?*)diffuseRadarViewWithStartRadius:(CGFloat)startRadius
?????????????????????????????????????endRadius:(CGFloat)endRadius
???????????????????????????????????circleColor:(UIColor?*)circleColor;
/**
?*??展示在targerView上
?*
?*??@param?targerView?
?*/
-?(void)showTargetView:(UIView?*)targerView;
-?(void)dismiss;
/**?開始掃描動(dòng)畫?*/
-?(void)startAnimatian;
/**?停止掃描動(dòng)畫?*/
-?(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;
/**?雷達(dá)?空心圓圈的數(shù)量?*/
@property?(nonatomic,?assign)?int?radarLineNum;
/**?中心?空心圓的半徑?(一般?這里放置一個(gè)圓形的頭像)?*/
@property?(nonatomic,?assign)?int?hollowRadius;
#pragma?mark?-?擴(kuò)散類型的RadarView?屬性
/**?擴(kuò)散動(dòng)畫?起始?的半徑?*/
@property?(nonatomic,?assign)?CGFloat?startRadius;
/**?擴(kuò)散動(dòng)畫?結(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;
????????}
????????
????????//?畫雷達(dá)線
????????[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è)置角度的大小,形成一個(gè)扇形
????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);?//繪制路徑
}
/**?畫雷達(dá)線?*/
-?(void)drawRadarLine?{
????CGFloat?minRadius?=?(_sectorRadius-_hollowRadius)*(pow(0.618,?_radarLineNum-1));
????/**?畫?圍著空心半徑的第一個(gè)空心圓,此圓不在計(jì)數(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?-?開始動(dòng)畫
-?(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é)束動(dòng)畫
-?(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對(duì)象解析成RGBA?值?的數(shù)組
?*
?*??@param?color?UIColor對(duì)象,有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];
????}];
}
@end3. 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];
????
????/**?擴(kuò)散?類型?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中直接使用。





