雷达和脉冲扫描图

作者: DDY | 来源:发表于2017-10-13 16:24 被阅读107次
    DDYRadarView.png DDYPulseView.png

    请关注,防止你用了,我改了,有问题连个商量的人都找不到...

    雷达扫描图

    DDYRadarView.h

    #import <UIKit/UIKit.h>
    
    @class DDYRadarView;
    @class DDYRadarPointView;
    
    //------------------------ 数据代理 ------------------------//
    @protocol DDYRadarViewDataSource <NSObject>
    @optional
    /** 点位数量 最大为8 */
    - (NSInteger)numberOfPointInRadarView:(DDYRadarView *)radarView;
    /** 点位视图 */
    - (DDYRadarPointView *)radarView:(DDYRadarView *)radarView viewForIndex:(NSInteger)index;
    /** 点位图片 */
    - (UIImage *)radarView:(DDYRadarView *)radarView imageForIndex:(NSInteger)index;
    
    @end
    
    //------------------------ 视图代理 ------------------------//
    @protocol DDYRadarViewDelegate <NSObject>
    @optional
    /** 点击点位回调 */
    - (void)radarView:(DDYRadarView *)radarView didSelectItemAtIndex:(NSInteger)index;
    
    @end
    
    //----------------------- 点位头像视图 -----------------------//
    @interface DDYRadarPointView : UIView
    
    @property (nonatomic, strong) UIImage *image;
    
    @end
    
    //------------------------ 扇形指示器 ------------------------//
    @interface DDYRadarIndicatorView : UIView
    
    @end
    
    //------------------------- 雷达视图 -------------------------//
    @interface DDYRadarView : UIView
    
    /** 数据源代理 */
    @property (nonatomic, weak) id <DDYRadarViewDataSource> dataSource;
    /** 视图代理 */
    @property (nonatomic, weak) id <DDYRadarViewDelegate> delegate;
    
    /** 同心圆半径 */
    @property (nonatomic, assign) CGFloat radius;
    /** 同心圆个数 */
    @property (nonatomic, assign) NSInteger circleNumber;
    /** 同心圆边框颜色 */
    @property (nonatomic, strong) UIColor *circleColor;
    /** 指示器开始颜色 */
    @property (nonatomic, strong) UIColor *indicatorStartColor;
    /** 指示器结束颜色 */
    @property (nonatomic, strong) UIColor *indicatorEndColor;
    /** 是否顺时针方向 */
    @property (nonatomic, assign) BOOL indicatorClockwise;
    /** 指示器角度大小 */
    @property (nonatomic, assign) CGFloat indicatorAngle;
    /** 指示器旋转速度 */
    @property (nonatomic, assign) CGFloat indicatorSpeed;
    /** 视图背景图片 */
    @property (nonatomic, strong) UIImage *backgroundImage;
    /** 显示虚分割线 */
    @property (nonatomic, assign) BOOL showSeparator;
    
    /** 雷达视图对象 */
    + (instancetype)radarView;
    /** 开始动画 */
    - (void)startScanAnimation;
    /** 结束动画 */
    - (void)stopScanAnimation;
    /** 刷新以展示数据 */
    - (void)reloadData;
    
    @end
    

    DDYRadarView.m

    #import "DDYRadarView.h"
    #import <QuartzCore/QuartzCore.h>
    
    //----------------------- 点位头像视图 -----------------------//
    @implementation DDYRadarPointView
    
    - (void)drawRect:(CGRect)rect {
        [super drawRect:rect];
        [_image drawInRect:self.bounds];
    }
    
    - (void)setImage:(UIImage *)image {
        _image = image;
        [self setNeedsDisplay];
    }
    
    @end
    
    //------------------------ 扇形指示器 ------------------------//
    @interface DDYRadarIndicatorView ()
    /** 半径 */
    @property (nonatomic, assign) CGFloat radius;
    /** 指示器开始颜色 */
    @property (nonatomic, strong) UIColor *startColor;
    /** 指示器结束颜色 */
    @property (nonatomic, strong) UIColor *endColor;
    /** 指示器角度 */
    @property (nonatomic, assign) CGFloat angle;
    /** 是否是否顺时针 */
    @property (nonatomic, assign) BOOL clockwise;
    
    @end
    
    @implementation DDYRadarIndicatorView
    
    - (void)drawRect:(CGRect)rect {
        [super drawRect:rect];
        // 画布
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        // 渐变色
        const CGFloat *startColorComponents = CGColorGetComponents(_startColor.CGColor);
        const CGFloat *endColorComponents = CGColorGetComponents(_endColor.CGColor);
        for (int i=0; i<_angle; i++) {
            CGFloat ratio = (_clockwise?(_angle-i):i)/_angle;
            CGFloat r = startColorComponents[0] - (startColorComponents[0]-endColorComponents[0])*ratio;
            CGFloat g = startColorComponents[1] - (startColorComponents[1]-endColorComponents[1])*ratio;
            CGFloat b = startColorComponents[2] - (startColorComponents[2]-endColorComponents[2])*ratio;
            CGFloat a = startColorComponents[3] - (startColorComponents[3]-endColorComponents[3])*ratio;
            
            // 画扇形
            CGContextSetFillColorWithColor(context, DDYColor(r, g, b, a).CGColor);
            CGContextSetLineWidth(context, 0);
            CGContextMoveToPoint(context, self.center.x, self.center.y);
            CGContextAddArc(context, self.center.x, self.center.y, _radius,  i*M_PI/180, (i + (_clockwise?-1:1))*M_PI/180, _clockwise);
            CGContextDrawPath(context, kCGPathFillStroke);
        }
    }
    
    @end
    
    //------------------------- 雷达视图 -------------------------//
    @interface DDYRadarView ()
    
    @property (nonatomic, strong) DDYRadarIndicatorView *indicatorView;
    
    @property (nonatomic, strong) UIView *pointsView;
    
    @end
    
    @implementation DDYRadarView
    
    + (instancetype)radarView {
        return [[self alloc] initWithFrame:[UIScreen mainScreen].bounds];
    }
    
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            [self prepare];
            [self addSubview:self.indicatorView];
        }
        return self;
    }
    
    - (void)prepare {
        _radius = self.ddy_w/2.-20;
        _circleNumber = 3;
        _circleColor = DDY_White;
        _indicatorStartColor = DDY_Blue;
        _indicatorEndColor = DDY_ClearColor;
        _indicatorClockwise = YES;
        _indicatorAngle = 360;
        _indicatorSpeed = 90;
        _backgroundImage = [UIImage imageWithColor:DDY_Gray size:DDYSCREENSIZE];
        _showSeparator = YES;
    }
    
    - (DDYRadarIndicatorView *)indicatorView {
        if (!_indicatorView) {
            _indicatorView = [[DDYRadarIndicatorView alloc] initWithFrame:self.bounds];
            _indicatorView.backgroundColor = DDY_ClearColor;
        }
        return _indicatorView;
    }
    
    - (void)resetIndicatorView {
        _indicatorView.radius = _radius;
        _indicatorView.angle = _indicatorAngle;
        _indicatorView.clockwise = _indicatorClockwise;
        _indicatorView.startColor = _indicatorStartColor;
        _indicatorView.endColor = _indicatorEndColor;
    }
    
    - (UIView *)pointsView {
        if (!_pointsView) {
            _pointsView = [[UIView alloc] initWithFrame:self.bounds].viewBGColor(DDY_ClearColor);
            [self insertSubview:_pointsView aboveSubview:self.indicatorView];
        }
        return _pointsView;
    }
    
    - (void)drawCircle {
        CGContextRef context = UIGraphicsGetCurrentContext();
        for (int i=0; i<_circleNumber; i++) {
            CGContextSetStrokeColorWithColor(context, _circleColor.CGColor);
            CGContextSetLineWidth(context, 1.);
            CGContextAddArc(context, self.center.x, self.center.y, _radius*(i+1)/_circleNumber, 0, 2*M_PI, 0);
            CGContextDrawPath(context, kCGPathStroke);
        }
    }
    
    - (void)drawSeparator {
        // 绘制
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetStrokeColorWithColor(context, _circleColor.CGColor);
        CGContextSetLineWidth(context, .7);
        CGFloat length1[] = {5, 5};
        CGContextSetLineDash(context, 0, length1, 2);
        
        for (int i=0; i<4; i++) {
            CGContextMoveToPoint(context, self.center.x+sinf(i*M_PI_4)*_radius, self.center.y-cosf(i*M_PI_4)*_radius);
            CGContextAddLineToPoint(context, self.center.x+sinf((i+4)*M_PI_4)*_radius, self.center.y-cosf((i+4)*M_PI_4)*_radius);
        }
        CGContextStrokePath(context);
    }
    
    - (void)drawRect:(CGRect)rect {
        [super drawRect:rect];
        [_backgroundImage drawInRect:self.bounds];
        [self resetIndicatorView];
        [self drawCircle];
        [self drawSeparator];
    }
    
    - (void)startScanAnimation {
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        animation.toValue = [NSNumber numberWithFloat:(_indicatorClockwise?1:-1) * M_PI * 2.];
        animation.duration = 360.f/_indicatorSpeed;
        animation.cumulative = YES;
        animation.repeatCount = INT_MAX;
        animation.removedOnCompletion = NO;
        animation.fillMode = kCAFillModeForwards;
        [self.indicatorView.layer addAnimation:animation forKey:@"rotationAnimation"];
    }
    
    - (void)stopScanAnimation {
        [self.indicatorView.layer removeAnimationForKey:@"rotationAnimation"];
    }
    
    #pragma mark 刷新以展示数据
    - (void)reloadData
    {
        [self.pointsView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
        
        if ([self.dataSource respondsToSelector:@selector(numberOfPointInRadarView:)])
        {
            for (int index=0; index<MIN([self.dataSource numberOfPointInRadarView:self], 8); index++)
            {
                DDYRadarPointView *pointView;
                if ([self.dataSource respondsToSelector:@selector(radarView:viewForIndex:)])
                {
                    pointView = [self.dataSource radarView:self viewForIndex:index];
                }
                else if ([self.dataSource respondsToSelector:@selector(radarView:imageForIndex:)])
                {
                    if ([self.dataSource radarView:self imageForIndex:index]) {
                        pointView = [[DDYRadarPointView alloc] init];
                        pointView.image = [self.dataSource radarView:self imageForIndex:index];
                    }
                }
                if (pointView) {
                    pointView.ddy_size = CGSizeMake(40, 40);
                    pointView.center = [self pointWithIndex:index];
                    pointView.tag = 100+index;
                    [pointView addTapTarget:self action:@selector(handleTopPointView:)];
                    [self.pointsView addSubview:pointView];
                    DDYBorderRadius(pointView, pointView.ddy_w/2., .7, DDY_White);
                }
            }
            
        }
    }
    
    #pragma mark 点位数组
    - (CGPoint)pointWithIndex:(NSInteger)index {
        CGPoint points[8];
        CGFloat radiusBig = _radius;
        CGFloat radiusMid = ((_circleNumber-1)*_radius/_circleNumber);
        points[0] = CGPointMake(self.center.x+sinf(0*M_PI_4)*radiusBig, self.center.y-cosf(0*M_PI_4)*radiusBig);
        points[1] = CGPointMake(self.center.x+sinf(4*M_PI_4)*radiusBig, self.center.y-cosf(4*M_PI_4)*radiusBig);
        points[2] = CGPointMake(self.center.x+sinf(6*M_PI_4)*radiusBig, self.center.y-cosf(6*M_PI_4)*radiusBig);
        points[3] = CGPointMake(self.center.x+sinf(2*M_PI_4)*radiusBig, self.center.y-cosf(2*M_PI_4)*radiusBig);
        points[4] = CGPointMake(self.center.x+sinf(1*M_PI_4)*radiusMid, self.center.y-cosf(1*M_PI_4)*radiusMid);
        points[5] = CGPointMake(self.center.x+sinf(3*M_PI_4)*radiusMid, self.center.y-cosf(3*M_PI_4)*radiusMid);
        points[6] = CGPointMake(self.center.x+sinf(7*M_PI_4)*radiusMid, self.center.y-cosf(7*M_PI_4)*radiusMid);
        points[7] = CGPointMake(self.center.x+sinf(5*M_PI_4)*radiusMid, self.center.y-cosf(5*M_PI_4)*radiusMid);
        return points[index];
    }
    
    - (void)handleTopPointView:(UITapGestureRecognizer *)gesture {
        if ([self.delegate respondsToSelector:@selector(radarView:didSelectItemAtIndex:)]) {
            [self.delegate radarView:self didSelectItemAtIndex:gesture.view.tag-100];
        }
    }
    
    #pragma mark - setter
    #pragma mark 同心圆半径
    - (void)setRadius:(CGFloat)radius {
        _radius = radius;
        [self setNeedsDisplay];
    }
    
    #pragma mark 同心圆个数
    - (void)setCircleNumber:(NSInteger)circleNumber {
        _circleNumber = circleNumber;
        [self setNeedsDisplay];
    }
    #pragma mark 同心圆边框颜色
    - (void)setCircleColor:(UIColor *)circleColor {
        _circleColor = circleColor;
        [self setNeedsDisplay];
    }
    
    #pragma mark 指示器开始颜色
    - (void)setIndicatorStartColor:(UIColor *)indicatorStartColor {
        _indicatorStartColor = indicatorStartColor;
        [self setNeedsDisplay];
    }
    
    #pragma mark 指示器结束颜色
    - (void)setIndicatorEndColor:(UIColor *)indicatorEndColor {
        _indicatorEndColor = indicatorEndColor;
        [self setNeedsDisplay];
    }
    
    #pragma mark 是否顺时针方向
    - (void)setIndicatorClockwise:(BOOL)indicatorClockwise {
        _indicatorClockwise = indicatorClockwise;
        [self setNeedsDisplay];
    }
    
    #pragma mark 指示器角度大小
    - (void)setIndicatorAngle:(CGFloat)indicatorAngle {
        _indicatorAngle = indicatorAngle;
        [self setNeedsDisplay];
    }
    
    #pragma mark 指示器旋转速度
    - (void)setIndicatorSpeed:(CGFloat)indicatorSpeed {
        _indicatorSpeed = indicatorSpeed;
        [self setNeedsDisplay];
    }
    
    #pragma mark 视图背景图片
    - (void)setBackgroundImage:(UIImage *)backgroundImage {
        _backgroundImage = backgroundImage;
        [self setNeedsDisplay];
    }
    
    #pragma mark 显示虚分割线
    - (void)setShowSeparator:(BOOL)showSeparator {
        _showSeparator = showSeparator;
        [self setNeedsDisplay];
    }
    
    @end
    

    应用DDYRadarVC.m

    #import "DDYRadarVC.h"
    
    @interface DDYRadarVC ()<DDYRadarViewDataSource, DDYRadarViewDelegate>
    
    @property (nonatomic, strong) DDYRadarView *radarView;
    
    @end
    
    @implementation DDYRadarVC
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [self.radarView startScanAnimation];
        [self.radarView reloadData];
        [self addObserverActive];
    }
    
    - (DDYRadarView *)radarView {
        if (!_radarView) {
            _radarView = [DDYRadarView radarView];
            _radarView.dataSource = self;
            _radarView.delegate = self;
            [self.view addSubview:self.radarView];
        }
        return _radarView;
    }
    
    - (NSInteger)numberOfPointInRadarView:(DDYRadarView *)radarView {
        return 8;
    }
    
    - (UIImage *)radarView:(DDYRadarView *)radarView imageForIndex:(NSInteger)index {
        return [UIImage imageWithColor:DDYRandomColor size:CGSizeMake(40, 40)];
    }
    
    - (void)radarView:(DDYRadarView *)radarView didSelectItemAtIndex:(NSInteger)index {
        DDYLog(@"click index:%ld",index);
    }
    
    #pragma mark 监听挂起和重新进入程序
    #pragma mark 添加监听
    - (void)addObserverActive
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:)
                                                     name:UIApplicationWillResignActiveNotification object:nil]; //监听home键挂起.
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:)
                                                     name:UIApplicationDidBecomeActiveNotification object:nil];  //监听重新进入程序.
    }
    
    #pragma mark 进入前台
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        [self.radarView startScanAnimation];
    }
    
    #pragma mark 挂起程序
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        [self.radarView stopScanAnimation];
    }
    
    @end
    

    脉冲扫描图

    DDYPulseView.h

    #import <UIKit/UIKit.h>
    
    //------------------------ 圆形视图 ------------------------//
    @interface DDYPulseCircleView : UIView
    
    @end
    
    //------------------------ 脉冲视图 ------------------------//
    @interface DDYPulseView : UIView
    
    /** 填充颜色 */
    @property (nonatomic, strong) UIColor *fillColor;
    /** 线条颜色 */
    @property (nonatomic, strong) UIColor *strokeColor;
    /** 最小圆半径 */
    @property (nonatomic, assign) CGFloat minRadius;
    
    /** 创建对象 */
    + (instancetype)pulseView;
    
    /** 开始动画 */
    - (void)startAnimation;
    
    /** 结束动画 */
     - (void)stopAnimation;
    
    @end
    

    DDYPulseView.m

    #import "DDYPulseView.h"
    
    //------------------------ 圆形视图 ------------------------//
    @interface DDYPulseCircleView ()
    /** 填充颜色 */
    @property (nonatomic, strong) UIColor *fillColor;
    /** 线条颜色 */
    @property (nonatomic, strong) UIColor *strokeColor;
    /** 初始最小半径 */
    @property (nonatomic, assign) CGFloat minRadius;
    
    @end
    
    @implementation DDYPulseCircleView
    
    - (void)drawRect:(CGRect)rect {
        [super drawRect:rect];
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetStrokeColorWithColor(context, _strokeColor.CGColor);
        CGContextSetFillColorWithColor(context, _fillColor.CGColor);
        CGContextAddArc(context, self.center.x, self.center.y, _minRadius, 0, 2*M_PI, 0);
        CGContextFillPath(context);
        CGContextDrawPath(context, kCGPathStroke);
    }
    
    @end
    
    //------------------------ 脉冲视图 ------------------------//
    @interface DDYPulseView ()
    
    @property (strong, nonatomic) NSTimer *timer;
    
    @end
    
    @implementation DDYPulseView
    
    + (instancetype)pulseView {
        return [[self alloc] initWithFrame:[UIScreen mainScreen].bounds];
    }
    
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            [self prepare];
        }
        return self;
    }
    
    - (void)prepare {
        _fillColor = [UIColor colorWithRed:23/255.0 green:1.0 blue:1.0 alpha:1.0];
        _strokeColor = [UIColor colorWithRed:23/255.0 green:1.0 blue:1.0 alpha:1.0];
        _minRadius = 30;
    }
    
    #pragma mark 开启定时器 开始动画
    - (void)startAnimation {
        [self stopAnimation];
        self.timer = [NSTimer scheduledTimerWithTimeInterval:0.6 target:self selector:@selector(radarAnimation) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    }
    
    #pragma mark 结束动画
    - (void)stopAnimation {
        if (self.timer) {
            [self.timer invalidate];
            self.timer = nil;
        }
    }
    
    #pragma mark 扫描动画
    - (void)radarAnimation
    {
        DDYPulseCircleView *circleView = [[DDYPulseCircleView alloc] initWithFrame:self.bounds];
        circleView.backgroundColor = DDY_ClearColor;
        circleView.fillColor = _fillColor;
        circleView.strokeColor = _strokeColor;
        circleView.minRadius = _minRadius;
        [self addSubview:circleView];
        
        [UIView animateWithDuration:3 animations:^{
            circleView.transform = CGAffineTransformScale(circleView.transform, DDYSCREENW/2/30, DDYSCREENW/2/30);
            circleView.alpha = 0;
        } completion:^(BOOL finished) {
            [circleView removeFromSuperview];
        }];
    }
    
    #pragma mark - setter
    #pragma mark 填充色
    - (void)setFillColor:(UIColor *)fillColor {
        _fillColor = fillColor;
        [self startAnimation];
    }
    
    #pragma mark 同心圆线条颜色
    - (void)setStrokeColor:(UIColor *)strokeColor {
        _strokeColor = strokeColor;
        [self startAnimation];
    }
    
    #pragma mark 最小圆半径
    - (void)setMinRadius:(CGFloat)minRadius {
        _minRadius = minRadius;
        [self startAnimation];
    }
    
    - (void)dealloc {
        [self stopAnimation];
    }
    
    @end
    

    应用 DDYPulseVC.m

    #import "DDYPulseVC.h"
    
    @interface DDYPulseVC ()
    
    @property (nonatomic, strong) DDYPulseView *pulseView;
    
    @end
    
    @implementation DDYPulseVC
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self.pulseView startAnimation];
        self.pulseView.fillColor = APP_MAIN_COLOR;
        self.pulseView.strokeColor = APP_MAIN_COLOR;
        self.pulseView.minRadius = 30;
    }
    
    - (DDYPulseView *)pulseView {
        if (!_pulseView) {
            _pulseView = [DDYPulseView pulseView];
            [self.view addSubview:_pulseView];
        }
        return _pulseView;
    }
    
    @end
    

    码农不易点星星 scan DDYRadarView code
    码农不易点星星 scan DDYPulseView code

    相关文章

      网友评论

        本文标题:雷达和脉冲扫描图

        本文链接:https://www.haomeiwen.com/subject/sjgzyxtx.html