用drawRect以及CAReplicatorLayer绘制动态水波纹

用drawRect以及CAReplicatorLayer绘制动态水波纹

大大简化了写水波纹效果的难度,你可以根据示例自己组装水波纹效果,本设计是几个工具组合在一起完成的效果, DrawRectObject 以及 ReplicatorLineAnimationView 均可以独立完成更复杂的功能.

说明

1. 用sine计算正玄曲线

2. 用CAReplicatorLayer实现重复移动的效果

效果

源码

https://github.com/YouXianMing/UI-Component-Collection 中的 DrawRectObject

//
//  WaveView.h
//  DrawRectObject
//
//  Created by YouXianMing on 16/8/1.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "CustomDrawingView.h"

typedef enum : NSUInteger {
    
    kStrokeWave = 1 << 2,
    kFillWave   = 1 << 3 ,
    
} EWaveViewType;

@interface WaveView : CustomDrawingView

/**
 *  Wave type, default is kFillWave.
 */
@property (nonatomic) EWaveViewType type;

/**
 *  Sine phase, default is 0.
 */
@property (nonatomic) CGFloat  phase;

/**
 *  Wave crest height, Default is 10.
 */
@property (nonatomic) CGFloat  waveCrest;

/**
 *  Full wave count,  default is 1.
 */
@property (nonatomic) NSInteger waveCount;

/**
 *  The fill style.
 */
@property (nonatomic, strong) DrawingStyle *fillStyle;

/**
 *  The stroke style.
 */
@property (nonatomic, strong) DrawingStyle *strokeStyle;

@end
//
//  WaveView.m
//  DrawRectObject
//
//  Created by YouXianMing on 16/8/1.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "WaveView.h"

@implementation WaveView

- (instancetype)initWithFrame:(CGRect)frame {
    
    if (self = [super initWithFrame:frame]) {
    
        self.waveCrest = 10.f;
        self.waveCount = 1;
        self.phase     = 0.f;
        self.type      = kFillWave;
        
        DrawingStyle *fillStyle = [DrawingStyle new];
        fillStyle.fillColor     = [DrawingColor colorWithUIColor:[[UIColor redColor] colorWithAlphaComponent:0.5f]];
        self.fillStyle          = fillStyle;
        
        DrawingStyle *strokeStyle = [DrawingStyle new];
        strokeStyle.strokeColor   = [DrawingColor colorWithUIColor:[UIColor redColor]];
        strokeStyle.lineWidth     = 0.5f;
        self.strokeStyle          = strokeStyle;
    }
    
    return self;
}

- (void)drawRect:(CGRect)rect {
    
    NSParameterAssert(self.fillStyle);
    NSParameterAssert(self.strokeStyle);

    [super drawRect:rect];
    
    CGFloat width  = self.frame.size.width;
    CGFloat height = self.frame.size.height;

    if (self.type & kFillWave) {
        
        [self.drawRectObject useDrawingStyle:_fillStyle drawFillBlock:^(DrawRectObject *drawRectObject) {
            
            for (CGFloat x = 0; x <= width; x++) {
                
                if (x == 0) {
                    
                    [drawRectObject moveToStartPoint:CGPointMake(x, _waveCrest * sin((2 * M_PI) * _waveCount / width * x + _phase) + height / 2.f)];
                    continue;
                    
                } else {
                    
                    [drawRectObject addLineToPoint:CGPointMake(x, _waveCrest * sin((2 * M_PI) * _waveCount / width * x + _phase) + height / 2.f)];
                }
            }
            
            [drawRectObject addLineToPoint:CGPointMake(width, height)];
            [drawRectObject addLineToPoint:CGPointMake(0, height)];
            [drawRectObject addLineToPoint:CGPointMake(0, _waveCrest * sin((2 * M_PI) * _waveCount / width * 0 + _phase) + height / 2.f)];
        }];
    }
    
    if (self.type & kStrokeWave) {
        
        [self.drawRectObject useDrawingStyle:_strokeStyle drawStrokeBlock:^(DrawRectObject *drawRectObject) {
            
            for (CGFloat x = 0; x <= width; x++) {
                
                if (x == 0) {
                    
                    [drawRectObject moveToStartPoint:CGPointMake(x, _waveCrest * sin((2 * M_PI) * _waveCount / width * x + _phase) + height / 2.f)];
                    continue;
                    
                } else {
                    
                    [drawRectObject addLineToPoint:CGPointMake(x, _waveCrest * sin((2 * M_PI) * _waveCount / width * x + _phase) + height / 2.f)];
                }
            }
        }];
    }
}

@end
//
//  ViewController.m
//  DrawRectObject
//
//  Created by YouXianMing on 16/7/30.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "ViewController.h"
#import "WaveView.h"
#import "ReplicatorLineAnimationView.h"
#import "UIView+SetRect.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    // Wave 1
    {
        WaveView *waveView = [[WaveView alloc] initWithFrame:CGRectMake(0, 0, Width, Height)];
        waveView.phase     = 0.f;
        waveView.waveCrest = 5.f;
        waveView.waveCount = 1;
        waveView.type      = kStrokeWave | kFillWave;
        
        {
            DrawingStyle *fillStyle = [DrawingStyle new];
            fillStyle.fillColor     = [DrawingColor colorWithUIColor:[[UIColor redColor] colorWithAlphaComponent:0.25f]];
            waveView.fillStyle      = fillStyle;
            
            DrawingStyle *strokeStyle = [DrawingStyle new];
            strokeStyle.strokeColor   = [DrawingColor colorWithUIColor:[[UIColor redColor] colorWithAlphaComponent:0.5f]];
            strokeStyle.lineWidth     = 0.5f;
            waveView.strokeStyle      = strokeStyle;
        }
        
        ReplicatorLineAnimationView *replicatorLineView = [[ReplicatorLineAnimationView alloc] initWithFrame:waveView.bounds];
        replicatorLineView.direction   = kReplicatorLeft;
        replicatorLineView.speed       = 0.1f;
        replicatorLineView.contentView = waveView;
        [replicatorLineView startAnimation];
        [self.view addSubview:replicatorLineView];
    }
    
    // Wave 2
    {
        WaveView *waveView = [[WaveView alloc] initWithFrame:CGRectMake(0, 0, Width, Height)];
        waveView.phase     = 0.f;
        waveView.waveCrest = 10.f;
        waveView.waveCount = 1;
        waveView.type      = kStrokeWave | kFillWave;
        
        {
            DrawingStyle *fillStyle = [DrawingStyle new];
            fillStyle.fillColor     = [DrawingColor colorWithUIColor:[[UIColor redColor] colorWithAlphaComponent:0.5f]];
            waveView.fillStyle      = fillStyle;
            
            DrawingStyle *strokeStyle = [DrawingStyle new];
            strokeStyle.strokeColor   = [DrawingColor colorWithUIColor:[UIColor redColor]];
            strokeStyle.lineWidth     = 0.5f;
            waveView.strokeStyle      = strokeStyle;
        }
        
        ReplicatorLineAnimationView *replicatorLineView = [[ReplicatorLineAnimationView alloc] initWithFrame:waveView.bounds];
        replicatorLineView.direction = kReplicatorLeft;
        replicatorLineView.speed     = 0.3f;
        replicatorLineView.contentView = waveView;
        [replicatorLineView startAnimation];
        [self.view addSubview:replicatorLineView];
    }
    
    // Wave 3
    {
        WaveView *waveView = [[WaveView alloc] initWithFrame:CGRectMake(0, 0, Width, Height)];
        waveView.phase     = 10.f;
        waveView.waveCrest = 15.f;
        waveView.waveCount = 1;
        waveView.type      = kFillWave;
        
        {
            DrawingStyle *fillStyle = [DrawingStyle new];
            fillStyle.fillColor     = [DrawingColor colorWithUIColor:[UIColor redColor]];
            waveView.fillStyle      = fillStyle;
        }
        
        ReplicatorLineAnimationView *replicatorLineView = [[ReplicatorLineAnimationView alloc] initWithFrame:waveView.bounds];
        replicatorLineView.direction   = kReplicatorLeft;
        replicatorLineView.speed       = 0.5f;
        replicatorLineView.contentView = waveView;
        [replicatorLineView startAnimation];
        [self.view addSubview:replicatorLineView];
    }
}

@end
原文地址:https://www.cnblogs.com/YouXianMing/p/5725482.html