iOS双波浪动画解析

作者: 船长_ | 来源:发表于2016-06-21 19:57 被阅读3546次
demo.gif

场景需求分析,如图

  • 1.自定义View
  • 2.利用CADisplayLink定时器,每秒60次刷新界面
  • 3.在View里面drawRect方法里,不停地绘制

1.需要用到的变量

@interface WaterView()
{
    UIColor *_waterColor;
    CGFloat _waterLineY;
    CGFloat _waveAmplitude;
    CGFloat _waveCycle;
    BOOL increase;
    CADisplayLink *_waveDisplayLink;
}

@end

2.初始化自定义的View

@implementation WaterView

-(instancetype)initWithFrame:(CGRect)frame
{
    self=[super initWithFrame:frame];
    if (self) {
        [self setBackgroundColor:[UIColor clearColor]];
        _waveAmplitude=3.0;
        _waveCycle=1.0;
        increase=NO;
        _waterColor=[UIColor colorWithRed:88/255.0f green:202/255.0f blue:139/255.0f alpha:1];
        _waterLineY=20.0;
        
        _waveDisplayLink=[CADisplayLink displayLinkWithTarget:self selector:@selector(runWave)];
        [_waveDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
    }
    return self;
}

3.定时器不停地调用的方法

-(void)runWave
{
    
    if (increase) {
        _waveAmplitude += 0.02;
    }else{
        _waveAmplitude -= 0.02;
    }
    
    
    if (_waveAmplitude<=1) {
        increase = YES;
    }
    
    if (_waveAmplitude>=1.5) {
        increase = NO;
    }
    
  // 控制玻璃滚动速度
    _waveCycle+=0.02;
    
    [self setNeedsDisplay];
}

4.核心代码,绘制波浪线

- (void)drawRect:(CGRect)rect
{
    //初始化画布
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    //推入
    CGContextSaveGState(context);
    
    //定义前波浪path
    CGMutablePathRef frontPath = CGPathCreateMutable();
    
    //定义后波浪path
    CGMutablePathRef backPath=CGPathCreateMutable();
    
    //定义前波浪反色path
    CGMutablePathRef frontReversePath = CGPathCreateMutable();
    
    //定义后波浪反色path
    CGMutablePathRef backReversePath=CGPathCreateMutable();
    
    //画水
    CGContextSetLineWidth(context, 1);
    
    //前波浪位置初始化
    float frontY=_waterLineY;
    CGPathMoveToPoint(frontPath, NULL, 0, frontY);
    
    //前波浪反色位置初始化
    float frontReverseY=_waterLineY;
    CGPathMoveToPoint(frontReversePath, NULL, 0,frontReverseY);
    
    //后波浪位置初始化
    float backY=_waterLineY;
    CGPathMoveToPoint(backPath, NULL, 0, backY);
    
    //后波浪反色位置初始化
    float backReverseY=_waterLineY;
    CGPathMoveToPoint(backReversePath, NULL, 0, backReverseY);
    
    for(float x=0;x<=ScreenWidth;x++){
        
        //前波浪绘制
        frontY= _waveAmplitude * sin( x/180*M_PI + 4*_waveCycle/M_PI ) * 5 + _waterLineY;
        CGPathAddLineToPoint(frontPath, nil, x, frontY);
        
        //后波浪绘制
        backY= _waveAmplitude * cos( x/180*M_PI + 3*_waveCycle/M_PI ) * 5 + _waterLineY;
        CGPathAddLineToPoint(backPath, nil, x, backY);
        
        if (x>=100) {
            
            //后波浪反色绘制
            backReverseY= _waveAmplitude * cos( x/180*M_PI + 3*_waveCycle/M_PI ) * 5 + _waterLineY;
            CGPathAddLineToPoint(backReversePath, nil, x, backReverseY);
            
            //前波浪反色绘制
            frontReverseY= _waveAmplitude * sin( x/180*M_PI + 4*_waveCycle/M_PI ) * 5 + _waterLineY;
            CGPathAddLineToPoint(frontReversePath, nil, x, frontReverseY);
        }
    }
    
    //后波浪绘制
    CGContextSetFillColorWithColor(context, [[FTFColor colorWithHexString:@"#ffefc9"] CGColor]);
    CGPathAddLineToPoint(backPath, nil, ScreenWidth, rect.size.height);
    CGPathAddLineToPoint(backPath, nil, 0, rect.size.height);
    CGPathAddLineToPoint(backPath, nil, 0, _waterLineY);
    CGPathCloseSubpath(backPath);
    CGContextAddPath(context, backPath);
    CGContextFillPath(context);
    
    //推入
    CGContextSaveGState(context);
    
    //后波浪反色绘制
    CGPathAddLineToPoint(backReversePath, nil, ScreenWidth, rect.size.height);
    CGPathAddLineToPoint(backReversePath, nil, 100, rect.size.height);
    CGPathAddLineToPoint(backReversePath, nil, 100, _waterLineY);
    
    CGContextAddPath(context, backReversePath);
    CGContextClip(context);
    
    // CGContextSaveGState(context);
    //弹出
    CGContextRestoreGState(context);
    
    //前波浪绘制
    CGContextSetFillColorWithColor(context, [_waterColor CGColor]);
    CGPathAddLineToPoint(frontPath, nil, ScreenWidth, rect.size.height);
    CGPathAddLineToPoint(frontPath, nil, 0, rect.size.height);
    CGPathAddLineToPoint(frontPath, nil, 0, _waterLineY);
    CGPathCloseSubpath(frontPath);
    CGContextAddPath(context, frontPath);
    CGContextFillPath(context);
    
    //推入
    CGContextSaveGState(context);
    
    
    //前波浪反色绘制
    CGPathAddLineToPoint(frontReversePath, nil, ScreenWidth, rect.size.height);
    CGPathAddLineToPoint(frontReversePath, nil, 100, rect.size.height);
    CGPathAddLineToPoint(frontReversePath, nil, 100, _waterLineY);
    
    CGContextAddPath(context, frontReversePath);
    CGContextClip(context);
    
    //推入
    CGContextSaveGState(context);
    
    //释放
    CGPathRelease(backPath);
    CGPathRelease(backReversePath);
    CGPathRelease(frontPath);
    CGPathRelease(frontReversePath);
}

附上原文gitHub地址,https://github.com/snapking/WaterWave

相关文章

  • iOS双波浪动画解析

    场景需求分析,如图 1.自定义View 2.利用CADisplayLink定时器,每秒60次刷新界面 3.在Vie...

  • ios - 波浪动画

    来源:http://summertreee.github.io/blog/2016/08/07/dong-hua-...

  • iOS知识点(14)核心动画Core Animation

    动画小王子写的书 iOS动画,绝对够分量! iOS动画篇_CoreAnimation(超详细解析核心动画) 老司机...

  • 【iOS】波浪动画实现

    最近项目中用到了一个波浪动画,于是我又重新复习了一遍正弦函数,并简单地封装了一个自定义视图。下面为大家介绍封装自定...

  • ios 相关知识复习

    1.CoreAnimation iOS动画篇_CoreAnimation(超详细解析核心动画) 扩展1彻底理解po...

  • App架构方方面面

    布局 揭秘 iOS 布局 Masonry源码解析 自动布局&绝对布局autolayoutautolayout 动画...

  • iOS 双曲线波浪动画

    今天来搞一下 双曲线波浪动画,那么什么是双曲线波浪呢 看效果 一,效果就是这样子 ,通过调整百分比 可以实现...

  • 【iOS】绘画波浪篇

    【iOS】绘画波浪篇 【iOS】绘画波浪篇

  • 波浪动画

    前言: 在多次地方我看到一个非常好看的线条动画-波浪。给人很舒服的赶脚,并且也很实用在项目中,比如:下载文件进度,...

  • iOS 简单的双层波浪动画

    具体实现 1、通过CADisplayLink 改变 CAShapeLayer.path 绘制三角函数曲线实现 y=...

网友评论

  • HeavenWong:反向怎么计算?? 波浪从左向右
    HeavenWong:还有一个问题, 怎么让波浪的波高从小到大,,,
    HeavenWong:@船长_ 666666
    船长_:@BabyWong for(float x=0;x<=ScreenWidth;x++){

    //前波浪绘制
    frontY= _waveAmplitude * sin( x/180*M_PI - 4*_waveCycle/M_PI ) * 5 + _waterLineY;
    CGPathAddLineToPoint(frontPath, nil, x, frontY);

    //后波浪绘制
    backY= _waveAmplitude * cos( x/180*M_PI - 3*_waveCycle/M_PI ) * 5 + _waterLineY;
    CGPathAddLineToPoint(backPath, nil, x, backY);

    if (x>=100) {

    //后波浪反色绘制
    backReverseY= _waveAmplitude * cos( x/180*M_PI - 3*_waveCycle/M_PI ) * 5 + _waterLineY;
    CGPathAddLineToPoint(backReversePath, nil, x, backReverseY);

    //前波浪反色绘制
    frontReverseY= _waveAmplitude * sin( x/180*M_PI - 4*_waveCycle/M_PI ) * 5 + _waterLineY;
    CGPathAddLineToPoint(frontReversePath, nil, x, frontReverseY);
    }
    }

本文标题:iOS双波浪动画解析

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