美文网首页
iOS 使用CAShapeLayer绘制一个动态的彩虹🌈

iOS 使用CAShapeLayer绘制一个动态的彩虹🌈

作者: 某非著名程序员 | 来源:发表于2019-08-09 21:31 被阅读0次
彩虹.gif

  分析:彩虹七种颜色,如果你做过弧形进度条,实现彩虹非常简单。
  我使用自定义的CAShapeLayer,没有采用UIView drawRect绘制,也没有使用UIView。由于只实现动画,不存在交互,CALayer比UIView有更好的性能。drawRect绘制属于软件绘制,比较耗内存。
  另外绘制圆的时候需要转成π,clockwise YES为顺时针、NO为逆时针。图中绘制的区域是π到3/2π。
  iOS动画是有渐变效果和缓冲效果的:

 CATransition *transition = [CATransition animation];
 transition.type = kCATransitionFade;
 transition.duration = 0.5;
 transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
 self.actions = @{@"path": transition};

  彩虹七种颜色,绘制七种弧度。下面直接贴代码:

//RainbowShapeLayerHeader.h代码
#define rainbow_lineWidth 4
#define rainbow_grow_rate 0.25

#import "RainbowShapeLayer.h"
#import "RainbowShapeLayerHeader.h"

@interface RainbowShapeLayer()
{
    CAShapeLayer * _shapeLayer;
    UIColor * _strokeColor;
}
@end

@implementation RainbowShapeLayer

- (instancetype)initWithStrokeColor:(UIColor *)strokeColor{
    self = [super init];
    if (self) {
        CATransition *transition = [CATransition animation];
        transition.type = kCATransitionFade;
        transition.duration = 0.5;
        transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        self.actions = @{@"path": transition};
        //set the p
        _strokeColor = strokeColor;
    }
    return self;
}

- (void)drawLineWithRadius:(CGFloat)radius endAngle:(CGFloat)endAngle{
    UIBezierPath * path = [[UIBezierPath alloc] init];
    [path addArcWithCenter:CGPointMake(200,300) radius:radius startAngle:M_PI endAngle:endAngle clockwise:YES];
    
    self.fillColor = [UIColor clearColor].CGColor;
    self.lineWidth = rainbow_lineWidth;
    self.lineJoin = kCALineJoinRound;
    self.lineCap = kCALineCapRound;
    self.strokeColor = _strokeColor.CGColor;
    self.path = path.CGPath;
    
}

@end

#import "RainbowViewController.h"
#import "RainbowShapeLayer.h"
#import "RainbowShapeLayerHeader.h"
#import "Macros.h"
@interface RainbowViewController ()
{
    CGFloat _timercount;
}
@property (nonatomic,strong) NSMutableArray<RainbowShapeLayer *> * rainbowArray;
@property (nonatomic, strong) CADisplayLink * displayLink;
@end

@implementation RainbowViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _timercount = 5;
    // Do any additional setup after loading the view.
    NSArray * colors = @[RGB_COLOR(252, 79, 96),
                         RGB_COLOR(252, 160, 50),
                         RGB_COLOR(255, 251, 143),
                         RGB_COLOR(92, 247, 94),
                         RGB_COLOR(71, 157, 250),
                         RGB_COLOR(62, 76, 241),
                         RGB_COLOR(145, 66, 248)];
    for (NSInteger i = colors.count-1; i>=0; i--) {
        RainbowShapeLayer * rainbow = [[RainbowShapeLayer alloc] initWithStrokeColor:colors[i]];
        rainbow.frame = self.view.frame;
        [self.rainbowArray addObject:rainbow];
        [self.view.layer addSublayer:rainbow];
    }
    [self drawRainbow:nil];
    
}

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self startTimer];
}

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [self stopTimer];
}

- (void)drawRainbow:(CADisplayLink *)timer{
    if (_timercount>=50) {
        _timercount = 5;
    }
    for (int i = 0;i<self.rainbowArray.count;i++) {
        CGFloat endAngle = M_PI+M_PI*((_timercount)/100.0);

        RainbowShapeLayer * rainbowView = self.rainbowArray[i];
        [rainbowView drawLineWithRadius:100+rainbow_lineWidth*i endAngle:endAngle];
        _timercount += rainbow_grow_rate;
    }
}

#pragma mark - timer
- (void)startTimer{
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawRainbow:)];
    self.displayLink.frameInterval = 3;
//    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:UITrackingRunLoopMode];

    
}

- (void)stopTimer{
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (NSMutableArray<RainbowShapeLayer *> *)rainbowArray{
    if (!_rainbowArray) {
        _rainbowArray = [NSMutableArray new];
    }
    return _rainbowArray;
}

@end

总结:
1.文中的方法不一定是最好的,我刚开始想用渐变的,后来发现渐变只能是方形的,做不到对线条渐变,采用了多条CAShapeLayer了。虽说实现不难,但调试还是需要花点时间的,另外也是对动画的一个实践。
2.有任何问题欢迎留言交流。

相关文章

网友评论

      本文标题:iOS 使用CAShapeLayer绘制一个动态的彩虹🌈

      本文链接:https://www.haomeiwen.com/subject/pgrkdctx.html