iOS实现雷达扫描效果
程序员文章站
2022-06-16 12:26:12
本文实例为大家分享了ios实现雷达扫描的具体代码,供大家参考,具体内容如下#import @interface ltindicatiorview : uiv...
本文实例为大家分享了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; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。