用drawRect以及CAReplicatorLayer繪製動態水波紋,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