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

iOS实现雷达扫描效果

程序员文章站 2022-06-16 12:26:12
本文实例为大家分享了ios实现雷达扫描的具体代码,供大家参考,具体内容如下#import @interface ltindicatiorview : uiv...

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

iOS实现雷达扫描效果

#import <uikit/uikit.h>
 
@interface ltindicatiorview : uiview
@property(nonatomic,strong)uicolor *color;
@property(nonatomic,assign)float repeatcount;
@property(nonatomic,strong)uicolor *bordercolor;
@property(nonatomic,assign)float borderwidth;
@end
 
@interface ltradarview : uiview
@property(nonatomic,strong)uicolor *color;
@property(nonatomic,strong)uicolor *bordercolor;
@property(nonatomic,assign)float borderwidth;
@property(nonatomic,assign)int pulsingcount;
@property(nonatomic,assign)float duration;
@property(nonatomic,assign)float repeatcount;
@property(nonatomic,strong)calayer *pulsinglayer;
 
 
@end

.m文件

//
//  ltradarview.m
//  raderscan
//
//  created by mac on 17/2/5.
//  copyright © 2017年 mac. all rights reserved.
//
 
#import "ltradarview.h"
 
#define angel 15
 
@interface ltradarbutton : uibutton
 
@end
 
@implementation ltradarbutton
 
- (void)removefromsuperview
{
    [uiview beginanimations:@"" context:nil];
    [uiview setanimationduration:0.5];
    self.transform = cgaffinetransformmakescale(0.2, 0.2);
    self.alpha = 0;
    [uiview setanimationdidstopselector:@selector(callsuperremovefromsuperview)];
    [uiview commitanimations];
 
}
 
- (void)callsuperremovefromsuperview
{
    [super removefromsuperview];
}
 
- (id)initwithframe:(cgrect)frame
{
    self = [super initwithframe:frame];
    self.alpha = 0;
    return self;
}
 
- (void)didmovetowindow
{
    [super didmovetowindow];
     self.transform = cgaffinetransformmakescale(0.2, 0.2);
    if (self.window) {
        [uiview animatewithduration:0.5 animations:^{
            self.transform = cgaffinetransformidentity;
            self.alpha = 1;
        }];
    }
    
}
 
 
 
@end
 
 
@implementation ltindicatiorview
 
- (id)initwithframe:(cgrect)frame
{
    if (self = [super initwithframe:frame]) {
        _color = [uicolor greencolor];
        _repeatcount = huge_valf;
        _bordercolor = [uicolor redcolor];
        _borderwidth = 1.0f;
    }
    return self;
}
 
 
 // only override drawrect: if you perform custom drawing.
 // an empty implementation adversely affects performance during animation.
 - (void)drawrect:(cgrect)rect {
 // drawing code
     
     self.backgroundcolor = [uicolor whitecolor];
     [super drawrect:rect];
     self.layer.cornerradius = self.frame.size.height/2.0f;
     self.clipstobounds = yes;
     self.layer.bordercolor = [uicolor clearcolor].cgcolor;
     self.layer.borderwidth = 50;
     self.layer.maskstobounds = yes;
     
     
     cgcontextref context = uigraphicsgetcurrentcontext();
     for (int i = 0; i < angel; i++) {
         cgfloat alpha = (float)i /(float)600;
         cgcolorref shadowcolor = [[uicolor greencolor] colorwithalphacomponent:alpha].cgcolor;//计算扇形填充颜色
         cgcontextsetfillcolorwithcolor(context, shadowcolor);
         cgcontextmovetopoint(context, self.center.x, self.center.y);//指定员心
         cgfloat startangle =  (-angel+i+1.15)/angel*(float)m_pi;
         cgfloat endangle = (-angel+i-1.15)/angel*(float)m_pi;
//         nslog(@"startangle = %f endangle = %f ,alpha = %f",startangle,endangle,alpha);
         cgcontextaddarc(context, self.center.x, self.center.y, self.frame.size.height/2.0f,0, 25, 1);//画一个扇形
         cgcontextclosepath(context);
         
         cgcontextdrawpath(context, kcgpathfill);//绘制扇形
 
     }
     
     cgcontextsetlinewidth(context, 1);//扫描线宽度
     cgcontextsetstrokecolorwithcolor(context, [_color colorwithalphacomponent:1].cgcolor);//扫描线颜色
     cgcontextmovetopoint(context, self.center.x, self.center.y);
     cgcontextaddlinetopoint(context, self.frame.size.height, self.center.y);
     cgcontextstrokepath(context);
     
     cgcontextsetrgbstrokecolor(context,255/255.0, 255/255.0, 255/255.0, 0.1);//最外面圆颜色
     cgcontextsetlinewidth(context, 10);//线宽度
     cgcontextaddarc(context, self.center.x, self.center.y, self.frame.size.height/2.0, 0, 2*m_pi, 1);//添加一个圆
     cgcontextdrawpath(context, kcgpathstroke);//绘制路径
     
     cgcontextstrokepath(context);//显示绘制
     
     
     //扫描动画
     cabasicanimation *rotateanimation = [cabasicanimation animation];
     rotateanimation.keypath = @"transform.rotation.z";
     rotateanimation.tovalue = @(2*m_pi);
     rotateanimation.duration = 3;
     rotateanimation.removedoncompletion = no;
     rotateanimation.repeatcount = _repeatcount;
    
     [self.layer addanimation:rotateanimation forkey:@"rotate_layer"];
 }
 
 
@end
 
 
@implementation ltradarview
{
    nsmutablearray *items;
}
 
 
- (id)initwithframe:(cgrect)frame
{
    if (self = [super initwithframe:frame]) {
        
        items = [nsmutablearray array];
        _color = [uicolor redcolor];
      
        _bordercolor = [uicolor greencolor];
        _pulsingcount = 3;
        _duration = 3;
        _repeatcount = huge_valf;
        _borderwidth = 3.0f;
    }
    return self;
}
 
// only override drawrect: if you perform custom drawing.
// an empty implementation adversely affects performance during animation.
- (void)drawrect:(cgrect)rect {
    // drawing code
    [super drawrect:rect];
    
    self.layer.cornerradius = self.frame.size.height/2;
    self.clipstobounds = yes;
    self.layer.bordercolor = [uicolor clearcolor].cgcolor;
    self.layer.bordercolor = [uicolor clearcolor].cgcolor;
    self.layer.borderwidth = 50;
    self.layer.maskstobounds = yes;
    
    cgcontextref ctx = uigraphicsgetcurrentcontext();
    cgcontextsetrgbfillcolor(ctx, 0/255.0, 0/255.0, 0/255.0, 1);//圆颜色
    cgcontextsetlinewidth(ctx, 1);//宽度
    cgcontextaddarc(ctx, self.center.x, self.center.y, self.frame.size.height/2, 0, 2*m_pi, 1);//添加一个圆
    cgcontextdrawpath(ctx, kcgpathstroke);//绘制
    cgcontextstrokepath(ctx);//显示
    
    calayer *animationlayer = [calayer layer];
    animationlayer.frame = self.layer.frame;
    for (int i = 0; i < _pulsingcount; i++) {
        
        calayer *pulsinglayer = [calayer layer];
        pulsinglayer.frame = cgrectmake(0, 0, rect.size.width, rect.size.height);
        pulsinglayer.bordercolor = [uicolor clearcolor].cgcolor;
        pulsinglayer.borderwidth = 1;
        pulsinglayer.cornerradius = rect.size.height/2;
        pulsinglayer.backgroundcolor = [uicolor redcolor].cgcolor;
        
        caanimationgroup *animationgroup = [caanimationgroup animation];
        animationgroup.fillmode = kcafillmodeboth;
        animationgroup.begintime = cacurrentmediatime() + (float) i * _duration / _pulsingcount;
        animationgroup.duration = _duration;
        animationgroup.repeatcount = huge_valf;
        animationgroup.timingfunction = [camediatimingfunction functionwithname:kcamediatimingfunctionlinear];
        animationgroup.autoreverses = no;
        animationgroup.delegate = self;
        animationgroup.removedoncompletion = no;
        
        cabasicanimation *scaleanimation = [cabasicanimation animation];
        scaleanimation.keypath = @"transform.scale";
        scaleanimation.removedoncompletion = no;
        scaleanimation.fromvalue = @(0.0f);
        scaleanimation.tovalue = @1.0f;
        scaleanimation.autoreverses = no;
        
        
        cakeyframeanimation *opacityanimation = [cakeyframeanimation animation];
        opacityanimation.keypath = @"opacity";
        opacityanimation.values = @[@1.0,@0.75,@0.5,@0.25,@0.0];
        opacityanimation.keytimes = @[@0.0,@0.25,@0.5,@0.75,@1];
        opacityanimation.autoreverses = no;
        opacityanimation.removedoncompletion = no;
        
        animationgroup.animations = @[scaleanimation,opacityanimation];
        [pulsinglayer addanimation:animationgroup forkey:@"pulsing"];
        
        [animationlayer addsublayer:pulsinglayer];
    }
    
    [self.layer addsublayer:animationlayer];
    
    [nstimer scheduledtimerwithtimeinterval:1 target:self selector:@selector(addorreplaceitem) userinfo:nil repeats:yes];
}
 
 
- (void)animation:(calayer *)layer
{
    caanimationgroup *animationgroup = [caanimationgroup animation];
    animationgroup.fillmode = kcafillmodeboth;
    animationgroup.begintime = cacurrentmediatime() + 1 * _duration / _pulsingcount;
    animationgroup.duration = _duration;
    animationgroup.repeatcount = huge_valf;
    animationgroup.timingfunction = [camediatimingfunction functionwithname:kcamediatimingfunctionlinear];
    animationgroup.autoreverses = no;
    animationgroup.delegate = self;
    animationgroup.removedoncompletion = no;
    
    cabasicanimation *scaleanimation = [cabasicanimation animation];
    scaleanimation.keypath = @"transform.scale";
    scaleanimation.removedoncompletion = no;
    scaleanimation.fromvalue = @(0.0f);
    scaleanimation.tovalue = @1.0f;
    scaleanimation.autoreverses = no;
    
    
    cakeyframeanimation *opacityanimation = [cakeyframeanimation animation];
    opacityanimation.keypath = @"opacity";
    opacityanimation.values = @[@1.0,@0.75,@0.5,@0.25,@0.0];
    opacityanimation.keytimes = @[@0.0,@0.25,@0.5,@0.75,@1];
    opacityanimation.autoreverses = no;
    opacityanimation.removedoncompletion = no;
    
    animationgroup.animations = @[scaleanimation,opacityanimation];
    [layer addanimation:animationgroup forkey:@"pulsing"];
    
    
}
 
#define randomcolor [uicolor colorwithred:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0]
/*
 生成一个在圆里面的坐标
 生成的坐标要围绕中心的绿点(圆心),让我们重新翻开数学课本,看看高中数学对三角函数的定义:
 在一个平面直角坐标系中,以原点为圆心,1 为半径画一个圆,这个圆交 x 轴于 a 点。以 o 为旋转中心,将 a 点逆时针旋转一定的角度α至 b 点,设此时 b 点的坐标是(x,y),那么此时 y 的值就叫做α的正弦,记作 sinα;此时 x 的值就叫做α的余弦,记作 cosα;y 与 x 的比值 y/x 就叫做α的正切,记作 tanα。
 
 任意角三角函数 正弦sinθ=y/r, 余弦cosθ=x/r,正切tanθ=y/x,余切cotθ=x/y,正割secθ=r/x,余割cscθ=r/y
 锐角三角函数 正弦sina=a/c, 余弦cosa=b/c,正切tana=a/b,余切cota=b/a,正割seca=c/b,余割csca=c/a
 
 还有一个很重要的公式:圆的参数方程:以点o(a,b)为圆心,以r为半径的圆的参数方程是 x=a+r*cosθ, y=b+r*sinθ, (其中θ为参数)
 到这里为止,思路就清晰了,以下是generatecenterpointinradar的方法实现:
 */
 
- (cgpoint)generatecenterpointinradar
{
    float  angle = arc4random() % 360;//随机一个角度
    float radius = arc4random() % (int)((self.bounds.size.width - 44)/2);//随机一个半径, 这里减去44是因为要把这个view显示在圆里面,如果不减44,则有可能会显示在圓外面
    double x = cos(angle) * radius;//计算随机出现的一个角度的x坐标 x=a+r*cosθ r = radius, θ = angle ,a = 圆心的x坐标
    double y = sin(angle) * radius;//计算随机出现的一个角度的y坐标 y=b+r*sinθ r = radius, θ = angle ,b = 圆心的y坐标
    return cgpointmake(x + self.bounds.size.width / 2, y + self.bounds.size.height / 2);//x y 分别加个圆心的坐标即self.center.x.y
}
 
- (void)addorreplaceitem
{
    int maxcount = 10;
    
    ltradarbutton *radarbutton = [ltradarbutton buttonwithtype:uibuttontypecustom];
    radarbutton.frame = cgrectmake(0, 0, 44, 44);
    radarbutton.backgroundcolor = randomcolor;
    radarbutton.layer.cornerradius = 44/2;
    
 
    do {
        cgpoint center = [self generatecenterpointinradar];
        radarbutton.center = cgpointmake(center.x, center.y);
    } while ([self itemframeintersectsinotheritem:radarbutton.frame]);
        
 
    [self addsubview:radarbutton];
    [items addobject:radarbutton];
    
    if (items.count > maxcount)
    {
        uiview * view = [items firstobject];
        [view removefromsuperview];
        [items removeobject:view];
    }
}
 
 
/*
 我们现在在生成每个item的center的时候,没有和已有的item进行比较,这是一个比较耗性能的操作,如果你的itemsize过大,maxcount过多,这甚至能导致死循环,如果是那样的话,你可能在对itemsize以及maxcount做出限制的同时,也对循环的数量也进行控制,如果在生成一个item的center的时候,进行了过多的循环,就可以视为进入死循环了,在这种情况下,你只能重新计算已有的centers。这里不考虑这种极端情况,因为目前的itemsize和maxcount的配合,不会出现死循环。
 我们添加一个itemframeintersectsinotheritem私有方法来判断是否和之前生成的center有了重叠:
 */
- (bool)itemframeintersectsinotheritem:(cgrect)frame
{
    for (uiview *item in items)
    {
        if (cgrectintersectsrect(item.frame, frame))
        {
            return yes;
        }
    }
    return no;
}

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

相关标签: iOS 雷达扫描