牛叉的demoiOS进阶之路 ios零碎记录

雷达和脉冲扫描图

2017-10-13  本文已影响107人  DDY
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

上一篇 下一篇

猜你喜欢

热点阅读