水波紋效果

QQ20170816-103932.gif

整體思路

1.創(chuàng)建路徑(path),使用正弦函數(shù)計算一點坐標(x,y),將所有的點連接成線,繪畫出路徑。
2.創(chuàng)建CAShapeLayer圖層,根據(jù)路徑繪畫出波形效果。
3.使用CADispalyLink定時器,改變路徑,做出動畫效果。

代碼說明

效果的實現(xiàn)主要是路徑的繪制。理解正弦和余弦函數(shù)最為關(guān)鍵??梢詤⒖?a href="http://www.itdecent.cn/p/44c904291a2e" target="_blank">iOS水波紋動畫詳解
代碼來源iOS 水波表現(xiàn)進度的動畫效果實現(xiàn)以及demo

注意問題

需要注意的問題ios坐標系x左邊是正方向,y下邊是正方向。繪畫出的路徑需要填充的區(qū)域如圖所示:

屏幕快照 2017-08-16 上午11.29.58.png

單個波形,有漸變效果

//
//  YSWaterWaveView.m
//  Wave
//
//  Created by moshuqi on 16/1/7.
//  Copyright ? 2016年 msq. All rights reserved.
//

#import "YSWaterWaveView.h"

@interface YSWaterWaveView ()

@property (nonatomic, strong) CADisplayLink *displayLink;

@property (nonatomic, strong) CAShapeLayer *waveLayer;  // 繪制波形
@property (nonatomic, strong) CAGradientLayer *gradientLayer;   // 繪制漸變

@property (nonatomic, strong) NSArray *colors;  // 漸變的顏色數(shù)組
@property (nonatomic, assign) CGFloat percent;  // 波浪上升的比例

// 繪制波形的變量定義,使用波形曲線y=Asin(ωx+φ)+k進行繪制
@property (nonatomic, assign) CGFloat waveAmplitude;  // 波紋振幅,A
@property (nonatomic, assign) CGFloat waveCycle;      // 波紋周期,T = 2π/ω

@property (nonatomic, assign) CGFloat offsetX;        // 波浪x位移,φ
@property (nonatomic, assign) CGFloat waveSpeed;      // 波紋速度,用來累加到相位φ上,達到波紋水平移動的效果

@property (nonatomic, assign) CGFloat currentWavePointY;    // 當前波浪高度,k
@property (nonatomic, assign) CGFloat waveGrowth;     // 波紋上升速度,累加到k上,達到波浪高度上升的效果

@property (nonatomic, assign) BOOL bWaveFinished;   // 上升完成

// 用來計算波峰一定范圍內(nèi)的波動值
@property (nonatomic, assign) BOOL increase;
@property (nonatomic, assign) CGFloat variable;

@end

@implementation YSWaterWaveView

static const CGFloat kExtraHeight = 20;     // 保證水波波峰不被裁剪,增加部分額外的高度

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        [self defaultConfig];
        
        self.backgroundColor = [UIColor colorWithRed:4 / 255.0 green:181 / 255.0 blue:108 / 255.0 alpha:1];
    }
    
    return self;
}

- (void)setGrowthSpeed:(CGFloat)growthSpeed
{
    self.waveGrowth = growthSpeed;
}

- (void)setGradientColors:(NSArray *)colors
{
    // 必須保證傳進來的參數(shù)為UIColor*的數(shù)組
    NSMutableArray *array = [NSMutableArray array];
    for (UIColor *color in colors)
    {
        [array addObject:(__bridge id)color.CGColor];
    }
    
    self.colors = array;
}

- (void)setColorsWithArray:(NSArray *)colors
{
    self.colors = colors;
}

- (void)defaultConfig
{
    // 默認設(shè)置一些屬性
    self.waveCycle = 1.66 * M_PI / CGRectGetWidth(self.frame);     // 影響波長
    self.currentWavePointY = CGRectGetHeight(self.frame) * self.percent;       // 波紋從下往上升起
    
    self.waveGrowth = 1.0;
    self.waveSpeed = 0.4 / M_PI;
    
    self.offsetX = 0;
}

- (void)resetProperty
{
    // 重置屬性
    self.currentWavePointY = CGRectGetHeight(self.frame) * self.percent;
    self.offsetX = 0;
    
    self.variable = 1.6;
    self.increase = NO;
}

- (void)resetLayer
{
    // 動畫開始之前重置layer
    if (self.waveLayer)
    {
        [self.waveLayer removeFromSuperlayer];
        self.waveLayer = nil;
    }
    self.waveLayer = [CAShapeLayer layer];
    
    // 設(shè)置漸變
    if (self.gradientLayer)
    {
        [self.gradientLayer removeFromSuperlayer];
        self.gradientLayer = nil;
    }
    self.gradientLayer = [CAGradientLayer layer];
    
    
    self.gradientLayer.frame = [self gradientLayerFrame];
    [self setupGradientColor];
    
    [self.gradientLayer setMask:self.waveLayer];
    [self.layer addSublayer:self.gradientLayer];
    
}

- (void)setupGradientColor
{
    // gradientLayer設(shè)置漸變色
    if ([self.colors count] < 1)
    {
        self.colors = [self defaultColors];
    }
    
    self.gradientLayer.colors = self.colors;
    
    //設(shè)定顏色分割點
    NSInteger count = [self.colors count];
    CGFloat d = 1.0 / count;
    
    NSMutableArray *locations = [NSMutableArray array];
    for (NSInteger i = 0; i < count; i++)
    {
        NSNumber *num = @(d + d * i);
        [locations addObject:num];
    }
    NSNumber *lastNum = @(1.0f);
    [locations addObject:lastNum];
    
    self.gradientLayer.locations = locations;
    
    // 設(shè)置漸變方向,從上往下
    self.gradientLayer.startPoint = CGPointMake(0, 0);
    self.gradientLayer.endPoint = CGPointMake(0, 1);
}

- (CGRect)gradientLayerFrame
{
    // gradientLayer在上升完成之后的frame值,如果gradientLayer在上升過程中不斷變化frame值會導(dǎo)致一開始繪制卡頓,所以只進行一次賦值
    
    CGFloat gradientLayerHeight = CGRectGetHeight(self.frame) * self.percent + kExtraHeight;
    
    if (gradientLayerHeight > CGRectGetHeight(self.frame))
    {
        gradientLayerHeight = CGRectGetHeight(self.frame);
    }
    
    CGRect frame = CGRectMake(0, CGRectGetHeight(self.frame) - gradientLayerHeight, CGRectGetWidth(self.frame), gradientLayerHeight);
    
    return frame;
}

- (NSArray *)defaultColors
{
    // 默認的漸變色
    UIColor *color0 = [UIColor colorWithRed:164 / 255.0 green:216 / 255.0 blue:222 / 255.0 alpha:1];
    UIColor *color1 = [UIColor colorWithRed:105 / 255.0 green:192 / 255.0 blue:154 / 255.0 alpha:1];
    
    NSArray *colors = @[(__bridge id)color0.CGColor, (__bridge id)color1.CGColor];
    return colors;
}

- (void)startWaveToPercent:(CGFloat)percent
{
    self.percent = percent;
    
    [self resetProperty];
    [self resetLayer];
    
    if (self.displayLink)
    {
        [self.displayLink invalidate];
        self.displayLink = nil;
    }
    
    self.bWaveFinished = NO;
    
    // 啟動同步渲染繪制波紋
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(setCurrentWave:)];
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

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

- (void)setCurrentWave:(CADisplayLink *)displayLink
{
    if ([self waveFinished])
    {
        self.bWaveFinished = YES;
        [self amplitudeReduce];
        // 減小到0之后動畫停止。
        NSLog(@"完成amplitude = %lf",self.waveAmplitude);
        if (self.waveAmplitude <= 0)
        {
            [self stopWave];
            return;
        }
    }
    else
    {
        // 波浪高度未到指定高度 繼續(xù)上漲
        [self amplitudeChanged];
        self.currentWavePointY -= self.waveGrowth;
    }
    
    self.offsetX += self.waveSpeed;
    [self setCurrentWaveLayerPath];
}

- (BOOL)waveFinished
{
    // 波浪上升動畫是否完成
    CGFloat d = CGRectGetHeight(self.frame) - CGRectGetHeight(self.gradientLayer.frame);
    CGFloat extraH = MIN(d, kExtraHeight);
    BOOL bFinished = self.currentWavePointY <= extraH;
    
    return bFinished;
}

- (void)setCurrentWaveLayerPath
{
    // 通過正弦曲線來繪制波浪形狀
    CGMutablePathRef path = CGPathCreateMutable();
    CGFloat y = self.currentWavePointY;
    
    CGPathMoveToPoint(path, nil, 0, y);
    CGFloat width = CGRectGetWidth(self.frame);
    NSLog(@"k == %lf",self.currentWavePointY);
    for (float x = 0.0f; x <= width; x++)
    {
        // 正弦波浪公式
        y = self.waveAmplitude * sin(self.waveCycle * x + self.offsetX) + self.currentWavePointY;
        //坐標系決定的 x和y的正方向向下。
        CGPathAddLineToPoint(path, nil, x, y);
    }
    
    //path 路徑封好
    CGPathAddLineToPoint(path, nil, width, CGRectGetHeight(self.frame));
    CGPathAddLineToPoint(path, nil, 0, CGRectGetHeight(self.frame));
    CGPathCloseSubpath(path);
    
    self.waveLayer.path = path;
    CGPathRelease(path);
}

- (void)amplitudeChanged
{
    // 波峰在一定范圍之內(nèi)進行輕微波動
    
    // 波峰該繼續(xù)增大或減小
    if (self.increase)
    {
        self.variable += 0.01;
    }
    else
    {
        self.variable -= 0.01;
    }
    
    // 變化的范圍
    if (self.variable <= 1)
    {
        self.increase = YES;
    }
    
    if (self.variable >= 1.6)
    {
        self.increase = NO;
    }
    NSLog(@"variable = %lf",self.variable);
    // 根據(jù)variable值來決定波峰
    self.waveAmplitude = self.variable * 5;
    NSLog(@"amplitude = %lf",self.waveAmplitude);

}

- (void)amplitudeReduce
{
    // 波浪上升完成后,波峰開始逐漸降低
    self.waveAmplitude -= 0.066;
}

@end

單個波形,無漸變效果

//
//  YSWaterWaveView.m
//  Wave
//
//  Created by moshuqi on 16/1/7.
//  Copyright ? 2016年 msq. All rights reserved.
//

#import "YSWaterWaveView.h"

@interface YSWaterWaveView ()

@property (nonatomic, strong) CADisplayLink *displayLink;

@property (nonatomic, strong) CAShapeLayer *waveLayer;  // 繪制波形
@property (nonatomic, strong) CAShapeLayer *waveLayerCos;  // 繪制余弦波形
@property (nonatomic, strong) CAGradientLayer *gradientLayer;   // 繪制漸變

@property (nonatomic, strong) NSArray *colors;  // 漸變的顏色數(shù)組
@property (nonatomic, assign) CGFloat percent;  // 波浪上升的比例

// 繪制波形的變量定義,使用波形曲線y=Asin(ωx+φ)+k進行繪制
@property (nonatomic, assign) CGFloat waveAmplitude;  // 波紋振幅,A
@property (nonatomic, assign) CGFloat waveCycle;      // 波紋周期,T = 2π/ω

@property (nonatomic, assign) CGFloat offsetX;        // 波浪x位移,φ
@property (nonatomic, assign) CGFloat waveSpeed;      // 波紋速度,用來累加到相位φ上,達到波紋水平移動的效果

@property (nonatomic, assign) CGFloat currentWavePointY;    // 當前波浪高度,k
@property (nonatomic, assign) CGFloat waveGrowth;     // 波紋上升速度,累加到k上,達到波浪高度上升的效果

@property (nonatomic, assign) BOOL bWaveFinished;   // 上升完成

// 用來計算波峰一定范圍內(nèi)的波動值
@property (nonatomic, assign) BOOL increase;
@property (nonatomic, assign) CGFloat variable;

@end

@implementation YSWaterWaveView

static const CGFloat kExtraHeight = 20;     // 保證水波波峰不被裁剪,增加部分額外的高度

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        [self defaultConfig];
        
        self.backgroundColor = [UIColor colorWithRed:4 / 255.0 green:181 / 255.0 blue:108 / 255.0 alpha:1];
    }
    
    return self;
}

- (void)setGrowthSpeed:(CGFloat)growthSpeed
{
    self.waveGrowth = growthSpeed;
}

- (void)setGradientColors:(NSArray *)colors
{
    // 必須保證傳進來的參數(shù)為UIColor*的數(shù)組
    NSMutableArray *array = [NSMutableArray array];
    for (UIColor *color in colors)
    {
        [array addObject:(__bridge id)color.CGColor];
    }
    
    self.colors = array;
}

- (void)setColorsWithArray:(NSArray *)colors
{
    self.colors = colors;
}

- (void)defaultConfig
{
    // 默認設(shè)置一些屬性
    self.waveCycle = 1.66 * M_PI / CGRectGetWidth(self.frame);     // 影響波長
    self.currentWavePointY = CGRectGetHeight(self.frame) * self.percent;       // 波紋從下往上升起
    
    self.waveGrowth = 1.0;
    self.waveSpeed = 0.4 / M_PI;
    
    self.offsetX = 0;
}

- (void)resetProperty
{
    // 重置屬性
    self.currentWavePointY = CGRectGetHeight(self.frame);
    self.offsetX = 0;
    
    self.variable = 1.6;
    self.increase = NO;
}

- (void)resetLayer
{
    // 動畫開始之前重置layer
    if (self.waveLayer)
    {
        [self.waveLayer removeFromSuperlayer];
        self.waveLayer = nil;
    }
    self.waveLayer = [CAShapeLayer layer];
    self.waveLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.width);
    self.waveLayer.backgroundColor = [UIColor orangeColor].CGColor;
    [self.layer addSublayer:self.waveLayer];
    
}

- (void)startWaveToPercent:(CGFloat)percent
{
    self.percent = percent;
    
    [self resetProperty];
    [self resetLayer];
    
    if (self.displayLink)
    {
        [self.displayLink invalidate];
        self.displayLink = nil;
    }
    
    self.bWaveFinished = NO;
    
    // 啟動同步渲染繪制波紋
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(setCurrentWave:)];
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

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

- (void)setCurrentWave:(CADisplayLink *)displayLink
{
    if ([self waveFinished])
    {
        self.bWaveFinished = YES;
        [self amplitudeReduce];
        // 減小到0之后動畫停止。
        NSLog(@"完成amplitude = %lf",self.waveAmplitude);
        if (self.waveAmplitude <= 0)
        {
            [self stopWave];
            return;
        }
    }
    else
    {
        // 波浪高度未到指定高度 繼續(xù)上漲
        [self amplitudeChanged];
        self.currentWavePointY -= self.waveGrowth;
    }
    
    self.offsetX += self.waveSpeed;
    [self setCurrentWaveLayerPath];
}

- (BOOL)waveFinished
{
    // 波浪上升動畫是否完成
    CGFloat d = CGRectGetHeight(self.frame) - CGRectGetHeight(self.waveLayer.frame)*self.percent;
    BOOL bFinished = self.currentWavePointY <= d;
    
    return bFinished;
}

- (void)setCurrentWaveLayerPath
{
    // 通過正弦曲線來繪制波浪形狀
    CGMutablePathRef path = CGPathCreateMutable();
    CGFloat y = self.currentWavePointY;
    
    CGPathMoveToPoint(path, nil, 0, y);
    CGFloat width = CGRectGetWidth(self.frame);
    NSLog(@"k == %lf",self.currentWavePointY);
    for (float x = 0.0f; x <= width; x++)
    {
        // 正弦波浪公式
        y = self.waveAmplitude * sin(self.waveCycle * x + self.offsetX) + self.currentWavePointY;
        //坐標系決定的 x和y的正方向向下。
        CGPathAddLineToPoint(path, nil, x, y);
    }
    
    //path 路徑封好
    CGPathAddLineToPoint(path, nil, width, CGRectGetHeight(self.frame));
    CGPathAddLineToPoint(path, nil, 0, CGRectGetHeight(self.frame));
    CGPathCloseSubpath(path);
    
    self.waveLayer.path = path;
    self.waveLayer.fillColor = [UIColor cyanColor].CGColor;
    CGPathRelease(path);
}

- (void)amplitudeChanged
{
    // 波峰在一定范圍之內(nèi)進行輕微波動
    
    // 波峰該繼續(xù)增大或減小
    if (self.increase)
    {
        self.variable += 0.01;
    }
    else
    {
        self.variable -= 0.01;
    }
    
    // 變化的范圍
    if (self.variable <= 1)
    {
        self.increase = YES;
    }
    
    if (self.variable >= 1.6)
    {
        self.increase = NO;
    }
    NSLog(@"variable = %lf",self.variable);
    // 根據(jù)variable值來決定波峰
    self.waveAmplitude = self.variable * 5;
    NSLog(@"amplitude = %lf",self.waveAmplitude);

}

- (void)amplitudeReduce
{
    // 波浪上升完成后,波峰開始逐漸降低
    self.waveAmplitude -= 0.066;
}

@end

雙波形,無漸變效果

//
//  YSWaterWaveView.m
//  Wave
//
//  Created by moshuqi on 16/1/7.
//  Copyright ? 2016年 msq. All rights reserved.
//

#import "YSWaterWaveView.h"

@interface YSWaterWaveView ()

@property (nonatomic, strong) CADisplayLink *displayLink;

@property (nonatomic, strong) CAShapeLayer *waveLayer;  // 繪制波形
@property (nonatomic, strong) CAShapeLayer *waveLayerCos;  // 繪制余弦波形
@property (nonatomic, strong) CAGradientLayer *gradientLayer;   // 繪制漸變

@property (nonatomic, strong) NSArray *colors;  // 漸變的顏色數(shù)組
@property (nonatomic, assign) CGFloat percent;  // 波浪上升的比例

// 繪制波形的變量定義,使用波形曲線y=Asin(ωx+φ)+k進行繪制
@property (nonatomic, assign) CGFloat waveAmplitude;  // 波紋振幅,A
@property (nonatomic, assign) CGFloat waveCycle;      // 波紋周期,T = 2π/ω

@property (nonatomic, assign) CGFloat offsetX;        // 波浪x位移,φ
@property (nonatomic, assign) CGFloat waveSpeed;      // 波紋速度,用來累加到相位φ上,達到波紋水平移動的效果

@property (nonatomic, assign) CGFloat currentWavePointY;    // 當前波浪高度,k
@property (nonatomic, assign) CGFloat waveGrowth;     // 波紋上升速度,累加到k上,達到波浪高度上升的效果

@property (nonatomic, assign) BOOL bWaveFinished;   // 上升完成

// 用來計算波峰一定范圍內(nèi)的波動值
@property (nonatomic, assign) BOOL increase;
@property (nonatomic, assign) CGFloat variable;

@end

@implementation YSWaterWaveView

static const CGFloat kExtraHeight = 20;     // 保證水波波峰不被裁剪,增加部分額外的高度

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        [self defaultConfig];
        
        self.backgroundColor = [UIColor colorWithRed:4 / 255.0 green:181 / 255.0 blue:108 / 255.0 alpha:1];
    }
    
    return self;
}

- (void)setGrowthSpeed:(CGFloat)growthSpeed
{
    self.waveGrowth = growthSpeed;
}

- (void)setGradientColors:(NSArray *)colors
{
    // 必須保證傳進來的參數(shù)為UIColor*的數(shù)組
    NSMutableArray *array = [NSMutableArray array];
    for (UIColor *color in colors)
    {
        [array addObject:(__bridge id)color.CGColor];
    }
    
    self.colors = array;
}

- (void)setColorsWithArray:(NSArray *)colors
{
    self.colors = colors;
}

- (void)defaultConfig
{
    // 默認設(shè)置一些屬性
    self.waveCycle = 1.66 * M_PI / CGRectGetWidth(self.frame);     // 影響波長
    self.currentWavePointY = CGRectGetHeight(self.frame) * self.percent;       // 波紋從下往上升起
    
    self.waveGrowth = 1.0;
    self.waveSpeed = 0.4 / M_PI;
    
    self.offsetX = 0;
}

- (void)resetProperty
{
    // 重置屬性
    self.currentWavePointY = CGRectGetHeight(self.frame);
    self.offsetX = 0;
    
    self.variable = 1.6;
    self.increase = NO;
}

- (void)resetLayer
{
    // 動畫開始之前重置layer
    if (self.waveLayer)
    {
        [self.waveLayer removeFromSuperlayer];
        self.waveLayer = nil;
    }
    self.waveLayer = [CAShapeLayer layer];
    self.waveLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.width);
    self.waveLayer.backgroundColor = [UIColor orangeColor].CGColor;
    self.waveLayer.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.3f].CGColor;
    [self.layer addSublayer:self.waveLayer];
    
    
    if (self.waveLayerCos)
    {
        [self.waveLayerCos removeFromSuperlayer];
        self.waveLayerCos = nil;
    }
    self.waveLayerCos = [CAShapeLayer layer];
    self.waveLayerCos.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.width);
    self.waveLayerCos.backgroundColor = [UIColor clearColor].CGColor;
    self.waveLayerCos.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.3f].CGColor;
//    self.waveLayerCos.opacity = 0.5;
    [self.layer addSublayer:self.waveLayerCos];

}

- (void)startWaveToPercent:(CGFloat)percent
{
    self.percent = percent;
    
    [self resetProperty];
    [self resetLayer];
    
    if (self.displayLink)
    {
        [self.displayLink invalidate];
        self.displayLink = nil;
    }
    
    self.bWaveFinished = NO;
    
    // 啟動同步渲染繪制波紋
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(setCurrentWave:)];
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

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

- (void)setCurrentWave:(CADisplayLink *)displayLink
{
    if ([self waveFinished])
    {
        self.bWaveFinished = YES;
        [self amplitudeReduce];
        // 減小到0之后動畫停止。
        NSLog(@"完成amplitude = %lf",self.waveAmplitude);
        if (self.waveAmplitude <= 0)
        {
            [self stopWave];
            return;
        }
    }
    else
    {
        // 波浪高度未到指定高度 繼續(xù)上漲
        [self amplitudeChanged];
        self.currentWavePointY -= self.waveGrowth;
    }
    
    self.offsetX += self.waveSpeed;
    [self setCurrentWaveLayerPath];
}

- (BOOL)waveFinished
{
    // 波浪上升動畫是否完成
    CGFloat d = CGRectGetHeight(self.frame) - CGRectGetHeight(self.waveLayer.frame)*self.percent;
    BOOL bFinished = self.currentWavePointY <= d;
    
    return bFinished;
}

- (void)setCurrentWaveLayerPath
{
    // 通過正弦曲線來繪制波浪形狀
    CGMutablePathRef path = CGPathCreateMutable();
    CGFloat y = self.currentWavePointY;
    
    CGPathMoveToPoint(path, nil, 0, y);
    CGFloat width = CGRectGetWidth(self.frame);
    NSLog(@"k == %lf",self.currentWavePointY);
    for (float x = 0.0f; x <= width; x++)
    {
        // 正弦波浪公式
        y = self.waveAmplitude * sin(self.waveCycle * x + self.offsetX) + self.currentWavePointY;
        //坐標系決定的 x和y的正方向向下。
        CGPathAddLineToPoint(path, nil, x, y);
    }
    
    //path 路徑封好
    CGPathAddLineToPoint(path, nil, width, CGRectGetHeight(self.frame));
    CGPathAddLineToPoint(path, nil, 0, CGRectGetHeight(self.frame));
    CGPathCloseSubpath(path);
    
    self.waveLayer.path = path;
    CGPathRelease(path);
    
    
    CGMutablePathRef pathCos = CGPathCreateMutable();
    
    CGPathMoveToPoint(pathCos, nil, 0, y);
    for (float x = 0.0f; x <= width; x++)
    {
        // 正弦波浪公式
        y = self.waveAmplitude * cos(self.waveCycle * x + self.offsetX) + self.currentWavePointY;
        //坐標系決定的 x和y的正方向向下。
        CGPathAddLineToPoint(pathCos, nil, x, y);
    }
    
    //path 路徑封好
    CGPathAddLineToPoint(pathCos, nil, width, CGRectGetHeight(self.frame));
    CGPathAddLineToPoint(pathCos, nil, 0, CGRectGetHeight(self.frame));
    CGPathCloseSubpath(pathCos);
    
    self.waveLayerCos.path = pathCos;
    
    CGPathRelease(pathCos);

}

- (void)amplitudeChanged
{
    // 波峰在一定范圍之內(nèi)進行輕微波動
    
    // 波峰該繼續(xù)增大或減小
    if (self.increase)
    {
        self.variable += 0.01;
    }
    else
    {
        self.variable -= 0.01;
    }
    
    // 變化的范圍
    if (self.variable <= 1)
    {
        self.increase = YES;
    }
    
    if (self.variable >= 1.6)
    {
        self.increase = NO;
    }
    NSLog(@"variable = %lf",self.variable);
    // 根據(jù)variable值來決定波峰
    self.waveAmplitude = self.variable * 5;
    NSLog(@"amplitude = %lf",self.waveAmplitude);

}

- (void)amplitudeReduce
{
    // 波浪上升完成后,波峰開始逐漸降低
    self.waveAmplitude -= 0.066;
}

@end

頭文件

//
//  YSWaterWaveView.h
//  Wave
//
//  Created by moshuqi on 16/1/7.
//  Copyright ? 2016年 msq. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface YSWaterWaveView : UIView

- (void)startWaveToPercent:(CGFloat)percent;

- (void)setGrowthSpeed:(CGFloat)growthSpeed;    // 設(shè)置上升速度
- (void)setGradientColors:(NSArray *)colors;    // 設(shè)置漸變色

@end

調(diào)用方法

   CGFloat d = 160;
    CGRect rect = CGRectMake(0, 0, d, d);
    YSWaterWaveView *waterWaveView = [[YSWaterWaveView alloc] initWithFrame:rect];
    
    waterWaveView.center = self.view.center;
    waterWaveView.layer.cornerRadius = d / 2;
    waterWaveView.clipsToBounds = YES;
    
    [self.view addSubview:waterWaveView];
    
    [waterWaveView startWaveToPercent:0.8];

正弦型函數(shù)解析式:y=Asin(ωx+φ)+k在本文中的使用
*A:振幅,振幅決定了波紋起伏的大小,是一個一直變化的值,而且當波紋達到想要的高度后振幅會逐漸減小至零,當振幅小于零時,波紋已經(jīng)成一條直線,在這里需要將定時器關(guān)閉。代碼中使用兩個變量(self.increase和self.variable)改變振幅的大小。
*w:角速度,和波長有關(guān)系,其他情況不變的情況下,角速度越大,單個波長的周
期(T = 2 *M_PI/W)越短,波長越短。代碼中角速度(self.waveCycle)是一個定值。
*x:點在x方向的位置。
*φ:初相位,代碼中使用self.offsetX來表示,通過self.waveSpeed改變self.offsetX大小。
*k:正弦函數(shù)在坐標系Y上的偏移量,想要達到的高度由它來控制,因為Y坐標正方向向下,所以代碼中控制它的變量(self.currentWavePointY)是遞減的,遞減變量用self.waveGrowth控制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容