欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS自定义雷达扫描扩散动画

程序员文章站 2022-06-16 12:33:11
本文实例为大家分享了ios实现雷达扫描扩散动画的具体代码,供大家参考,具体内容如下自己自定义了 一个雷达扫描/扩散效果的view。扫描view 效果如下:扩散view 效果如下:自定义的代码如下:1....

本文实例为大家分享了ios实现雷达扫描扩散动画的具体代码,供大家参考,具体内容如下

自己自定义了 一个雷达扫描/扩散效果的view。

扫描view 效果如下:

iOS自定义雷达扫描扩散动画

扩散view 效果如下:

iOS自定义雷达扫描扩散动画

自定义的代码如下:

1. radarview.h

#import <uikit/uikit.h>
 
typedef 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;
/** 扇形结束颜色 必须由rgba值初始化
 *  [uicolor colorwithred: green: blue: alpha:]
 */
@property (nonatomic, strong) uicolor * endcolor;
 
/**
 *
 *  @param radius       半径
 *  @param angle        角度
 *  @param radarlinenum 雷达线数量
 *  @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 <#targerview description#>
 */
- (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;
/** 雷达 空心圆圈的数量 */
@property (nonatomic, assign) int radarlinenum;
/** 中心 空心圆的半径 (一般 这里放置一个圆形的头像) */
@property (nonatomic, assign) int hollowradius;
 
#pragma mark - 扩散类型的radarview 属性
/** 扩散动画 起始 的半径 */
@property (nonatomic, assign) cgfloat startradius;
/** 扩散动画 结束 的半径 */
@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 {
    //画扇形,也就画圆,只不过是设置角度的大小,形成一个扇形
    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));
    /** 画 围着空心半径的第一个空心圆,此圆不在计数内 */
    [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 - 结束动画
- (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 值 的数组
 *
 *  @param color uicolor对象,有rgba值 初始化的
 *[uicolor colorwithred:rvalue green:gvalue blue:bvalue alpha:avalue]
 *
 *  @return 包含rgba值得数组[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

现在定义的是能代码加载使用,等有空了,再封装一些方法能在storyboard中直接使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

相关标签: iOS 扫描 扩散