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;
}

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

时间: 2021-10-08

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

本文实例为大家分享了iOS实现雷达扫描扩散动画的具体代码,供大家参考,具体内容如下 自己自定义了 一个雷达扫描/扩散效果的View. 扫描View 效果如下: 扩散View 效果如下: 自定义的代码如下: 1. RadarView.h #import <UIKit/UIKit.h> typedef NS_ENUM(NSInteger, RadarViewType) { RadarViewTypeScan, RadarViewTypeDiffuse }; @interface RadarView

iOS 雷达效果实例详解

iOS雷达效果 这段时间新app开始了,有个产品需求是做一个类似如下效果的雷达图: 中间的图片是用户头像,然后需要展示一个雷达扫描的效果. 分析下雷达图的大致构成: 底部一个呈现用户头像的UIImageView 几个颜色渐变的同心圆,这些同心圆. 只需要在雷达视图的drawRect方法里画就可以了 盖在最上层的一个扇形,且扇形的圆心和雷达图视图的圆心是同一个点.扫描效果就是让这个扇形绕圆心转,因此把这个扇形抽成一个单独的类比较好. 同时这个雷达图应该提供两个接口:开始动画,暂停动画.因此雷达图的

微信小程序 利用css实现遮罩效果实例详解

微信小程序 利用css实现遮罩效果实例详解 实现效果图: 如图所示,使用css实现小程序的遮罩效果,代码如下 js文件代码: //index.js //获取应用实例 var app = getApp() Page({ data: { flag: false }, a: function(){ this.setData({flag: false}) }, b: function(){ this.setData({flag: true}) } }) wxss文件代码: .b1{position:fi

Bootstrap与KnockoutJs相结合实现分页效果实例详解

KnockoutJS是一个JavaScript实现的MVVM框架.非常棒.比如列表数据项增减后,不需要重新刷新整个控件片段或自己写JS增删节点,只要预先定义模板和符合其语法定义的属性即可.简单的说,我们只需要关注数据的存取. 一.引言 由于最近公司的系统需要改版,改版的新系统我打算使用KnockoutJs来制作Web前端.在做的过程中,遇到一个问题--如何使用KnockoutJs来完成分页的功能.在前一篇文章中并没有介绍使用KnockoutJs来实现分页,所以在这篇文章中,将补充用Knockou

Android ImageView的selector效果实例详解

Android ImageView的selector效果实例详解 在平时开发中如Button我们给它加上selector分别呈现pressed以及normal效果能给我们的用户体验上大大增色不少,可是我们当我们是用ImageView来"当作"一个一个"Button"的时候发现直接设置selector却不起作用,当然此时我们的应用就表现的暗淡了.那我们就只能找到方法来解决这种情况. 首先定义一个selector文件: <selector xmlns:androi

vue.js2.0 实现better-scroll的滚动效果实例详解

什么是 better-scroll better-scroll 是一个移动端滚动的解决方案,它是基于 iscroll 的重写,它和 iscroll 的主要区别在这里 .better-scroll 也很强大,不仅可以做普通的滚动列表,还可以做轮播图.picker 等等. <template> <div> <div class="goods"> <div class="menu-wrapper" ref="menuWr

Vue实现星级评价效果实例详解

我们把星级评价单独做成一个Star组件,抽离出来,其中父组件中引入(传入的是评分的值) <div class="score"> <Star :score="poiInfo.wm_poi_score"></Star> </div> 初始Star.vue <template> <div> <div class="star"> <span class="

JQuery标签页效果实例详解

本文实例讲述了JQuery标签页效果实现方法.分享给大家供大家参考,具体如下: 第一个标签页中鼠标滑过显示不同的标签页,第二个标签页中点击不同标签加载其他页面中的内容,加载等待的图片缓慢隐藏,效果图如下: /WebRoot/4.Tab.html: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> &l

jQuery实现的自定义弹出层效果实例详解

本文实例讲述了jQuery实现的自定义弹出层效果.分享给大家供大家参考,具体如下: dialog.css: #DialogBySHFLayer { width:100%; height:100%; left:0; top:0; position:fixed; z-index:500; background-color:#333333; filter:alpha(Opacity=40); -moz-opacity:0.4; opacity: 0.4; } /*弹出的提示框*/ #DialogByS

Android中ViewFlipper的使用及设置动画效果实例详解

本文实例讲述了Android中ViewFlipper的使用及设置动画效果.分享给大家供大家参考,具体如下: 说到左右滑动,其实实现左右滑动的方式很多,有ViewPaer,自定义实现Viewgroup,gallery等都可以达到这种效果.这里做下ViewFliper实现左右滑动的效果. 会用到以下的技术: 1.ViewFlipper 2.GestureDetector 3.Animation 主要是这三个类在起作用. ViewFlipper,不妨把它看做一个容器吧,你可以把许多的View放在这个容

Android自定义控件eBook实现翻书效果实例详解

本文实例讲述了Android自定义控件eBook实现翻书效果的方法.分享给大家供大家参考,具体如下: 效果图: Book.java文件: package com.book; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.ImageView; public class Book extend