水波纹效果

作者: 淘代码者 | 来源:发表于2017-08-16 12:02 被阅读28次
    QQ20170816-103932.gif

    整体思路

    1.创建路径(path),使用正弦函数计算一点坐标(x,y),将所有的点连接成线,绘画出路径。
    2.创建CAShapeLayer图层,根据路径绘画出波形效果。
    3.使用CADispalyLink定时器,改变路径,做出动画效果。

    代码说明

    效果的实现主要是路径的绘制。理解正弦和余弦函数最为关键。可以参考iOS水波纹动画详解
    代码来源iOS 水波表现进度的动画效果实现以及demo

    注意问题

    需要注意的问题ios坐标系x左边是正方向,y下边是正方向。绘画出的路径需要填充的区域如图所示:

    屏幕快照 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;  // 渐变的颜色数组
    @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;   // 上升完成
    
    // 用来计算波峰一定范围内的波动值
    @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
    {
        // 必须保证传进来的参数为UIColor*的数组
        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
    {
        // 默认设置一些属性
        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];
        
        // 设置渐变
        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设置渐变色
        if ([self.colors count] < 1)
        {
            self.colors = [self defaultColors];
        }
        
        self.gradientLayer.colors = self.colors;
        
        //设定颜色分割点
        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;
        
        // 设置渐变方向,从上往下
        self.gradientLayer.startPoint = CGPointMake(0, 0);
        self.gradientLayer.endPoint = CGPointMake(0, 1);
    }
    
    - (CGRect)gradientLayerFrame
    {
        // gradientLayer在上升完成之后的frame值,如果gradientLayer在上升过程中不断变化frame值会导致一开始绘制卡顿,所以只进行一次赋值
        
        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
        {
            // 波浪高度未到指定高度 继续上涨
            [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
    {
        // 波峰在一定范围之内进行轻微波动
        
        // 波峰该继续增大或减小
        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);
        // 根据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;  // 渐变的颜色数组
    @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;   // 上升完成
    
    // 用来计算波峰一定范围内的波动值
    @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
    {
        // 必须保证传进来的参数为UIColor*的数组
        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
    {
        // 默认设置一些属性
        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
        {
            // 波浪高度未到指定高度 继续上涨
            [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
    {
        // 波峰在一定范围之内进行轻微波动
        
        // 波峰该继续增大或减小
        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);
        // 根据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;  // 渐变的颜色数组
    @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;   // 上升完成
    
    // 用来计算波峰一定范围内的波动值
    @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
    {
        // 必须保证传进来的参数为UIColor*的数组
        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
    {
        // 默认设置一些属性
        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
        {
            // 波浪高度未到指定高度 继续上涨
            [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
    {
        // 波峰在一定范围之内进行轻微波动
        
        // 波峰该继续增大或减小
        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);
        // 根据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;    // 设置上升速度
    - (void)setGradientColors:(NSArray *)colors;    // 设置渐变色
    
    @end
    

    调用方法

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

    正弦型函数解析式:y=Asin(ωx+φ)+k在本文中的使用
    *A:振幅,振幅决定了波纹起伏的大小,是一个一直变化的值,而且当波纹达到想要的高度后振幅会逐渐减小至零,当振幅小于零时,波纹已经成一条直线,在这里需要将定时器关闭。代码中使用两个变量(self.increase和self.variable)改变振幅的大小。
    *w:角速度,和波长有关系,其他情况不变的情况下,角速度越大,单个波长的周
    期(T = 2 *M_PI/W)越短,波长越短。代码中角速度(self.waveCycle)是一个定值。
    *x:点在x方向的位置。
    *φ:初相位,代码中使用self.offsetX来表示,通过self.waveSpeed改变self.offsetX大小。
    *k:正弦函数在坐标系Y上的偏移量,想要达到的高度由它来控制,因为Y坐标正方向向下,所以代码中控制它的变量(self.currentWavePointY)是递减的,递减变量用self.waveGrowth控制。

    相关文章

      网友评论

        本文标题:水波纹效果

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