美文网首页动画
iOS水波动画实现

iOS水波动画实现

作者: JasonEVA | 来源:发表于2016-12-15 14:30 被阅读521次

    效果如下:


    12345.gif

    实现这个水波动画主要还是要利用下初中的知识:正弦函数

    y =Asin(ωx+φ)+C 
    

    A 表示振幅,也就是使用这个变量来调整波浪的高度 ω表示周期,也就是使用这个变量来调整在屏幕内显示的波浪的数量 φ表示波浪横向的偏移,也就是使用这个变量来调整波浪的流动 C表示波浪纵向的位置,也就是使用这个变量来调整波浪在屏幕中竖直的位置。

    主要原理

    CADisplayLink的对象也是一个定时器。适用于UI的不停刷新,如自定义动画引擎或者视频的渲染。CADisplayLink 对象注册到Runloop之后。屏幕刷新的时候定时器就会被触发。iOS设备的刷新频率是60HZ也就是60帧也就是每秒刷新60次,也可以通过设置frameInterval属性为2那么两帧才会刷新一次。 CAShapeLayer 的对象是一个本身没有形状,他的形状来源于你给定的Path,它依附于path,所以必须给定path,即使path不完整也会自动收尾相接,strokeStart以及stroleEnd代表着这个path中所占的百分比(可以使用storkeStart和stroleEnd来做曲线进度的动画)。

    代码实现

    创建一个动画View

    #import <UIKit/UIKit.h>
    
    @interface JWWavesAnimationView : UIView
    - (void)setUp; //开始布局@end
    

    .m

    /*
     正弦函数
    y =Asin(ωx+φ)+C
    A 表示振幅,也就是使用这个变量来调整波浪的高度
    ω表示周期,也就是使用这个变量来调整在屏幕内显示的波浪的数量
    φ表示波浪横向的偏移,也就是使用这个变量来调整波浪的流动
    C表示波浪纵向的位置,也就是使用这个变量来调整波浪在屏幕中竖直的位置。
    */
    
    
    #import "JWWavesAnimationView.h"
    
    @interface JWWavesAnimationView ()
    @property (nonatomic, strong) CADisplayLink *waveDisplaylink;
    @property (nonatomic, strong) CAShapeLayer *firstWaveLayer;
    @property (nonatomic, strong) CAShapeLayer *secondWaveLayer;
    
    @property (nonatomic) CGFloat waveA; //水纹振幅    表示上面的A
    @property (nonatomic) CGFloat waveW;//水纹周期  表示上面的ω
    @property (nonatomic) CGFloat offsetX; //位移   表示上面的φ
    @property (nonatomic) CGFloat currentK; //当前波浪高度Y   表示上面的C
    @property (nonatomic) CGFloat waveSpeed;//水纹速度   表示波浪流动的速度
    @property (nonatomic) CGFloat waterWaveWidth; //水纹宽度
    @property (nonatomic, strong) UIColor *firstWaveColor; //波浪的颜色
    
    @end
    
    @implementation JWWavesAnimationView
    
    - (instancetype)init {
        if (self = [super init]) {
            self.backgroundColor = [UIColor whiteColor];
            self.layer.masksToBounds  = YES;
        }
        return self;
    }
    
    - (void)setUp {
        //设置波浪的宽度
        self.waterWaveWidth = self.bounds.size.width;
        //设置波浪的颜色
        self.firstWaveColor = [UIColor colorWithWhite:0.6 alpha:0.2];
        //设置波浪的速度
        self.waveSpeed = 0.4/M_PI;
        //初始化layer
        if (_firstWaveLayer == nil) {
            //初始化
            _firstWaveLayer = [CAShapeLayer layer];
            //设置闭环的颜色
            _firstWaveLayer.fillColor = _firstWaveColor.CGColor;
            //设置边缘线的颜色
    //        _firstWaveLayer.strokeColor = [UIColor blueColor].CGColor;
    //        //设置边缘线的宽度
    //        _firstWaveLayer.lineWidth = 4.0;
    //        _firstWaveLayer.strokeStart = 0.0;
    //        _firstWaveLayer.strokeEnd = 0.8;
            [self.layer addSublayer:_firstWaveLayer];
        }
        if (self.secondWaveLayer == nil) {
            //初始化
            self.secondWaveLayer = [CAShapeLayer layer];
            //设置闭环的颜色
            self.secondWaveLayer.fillColor = _firstWaveColor.CGColor;
            //设置边缘线的颜色
            //        _firstWaveLayer.strokeColor = [UIColor blueColor].CGColor;
            //        //设置边缘线的宽度
            //        _firstWaveLayer.lineWidth = 4.0;
            //        _firstWaveLayer.strokeStart = 0.0;
            //        _firstWaveLayer.strokeEnd = 0.8;
            [self.layer addSublayer:self.secondWaveLayer];
        }
        //设置波浪流动速度
        self.waveSpeed = 0.1;
        //设置振幅
        self.waveA = 5;
        //设置周期
        self.waveW = 1/20.0;
        //设置波浪纵向位置
        self.currentK = self.frame.size.height/2;//屏幕居中
        //启动定时器
        self.waveDisplaylink = [CADisplayLink displayLinkWithTarget:self selector:@selector(getCurrentWave:)];
        [self.waveDisplaylink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
    
    }
    
    -(void)getCurrentWave:(CADisplayLink *)displayLink
    {
        //实时的位移
        self.offsetX += self.waveSpeed;
        [self setCurrentFirstWaveLayerPath];
        [self setCurrentSecondWaveLayerPath];
    }
    
    -(void)setCurrentFirstWaveLayerPath
    {
        //创建一个路径
        CGMutablePathRef path = CGPathCreateMutable();
        CGFloat y = self.currentK;
        //将点移动到 x=0,y=currentK的位置
        CGPathMoveToPoint(path, nil, 0, y);
        for (NSInteger x = 0.0f; x<=self.waterWaveWidth; x++) {
            //正玄波浪公式
            y = self.waveA * sin(self.waveW * x+ self.offsetX)+self.currentK;
            //将点连成线
            CGPathAddLineToPoint(path, nil, x, y);
        }
        CGPathAddLineToPoint(path, nil, self.waterWaveWidth, self.frame.size.height);
        CGPathAddLineToPoint(path, nil, 0, self.frame.size.height);
        CGPathCloseSubpath(path);
        _firstWaveLayer.path = path;
        CGPathRelease(path);
    }
    
    -(void)setCurrentSecondWaveLayerPath
    {
        //创建一个路径
        CGMutablePathRef path = CGPathCreateMutable();
        CGFloat y = self.currentK;
        //将点移动到 x=0,y=currentK的位置
        CGPathMoveToPoint(path, nil, 0, y);
        for (NSInteger x = 0.0f; x<=self.waterWaveWidth; x++) {
            //正玄波浪公式
            y = (self.waveA+2) * sin(self.waveW * x- self.offsetX + 10)+self.currentK;
            //将点连成线
            CGPathAddLineToPoint(path, nil, x, y);
        }
        CGPathAddLineToPoint(path, nil, self.waterWaveWidth, self.frame.size.height);
        CGPathAddLineToPoint(path, nil, 0, self.frame.size.height);
        CGPathCloseSubpath(path);
        self.secondWaveLayer.path = path;
        CGPathRelease(path);
    }
    
    - (void)dealloc
    {
        [_waveDisplaylink invalidate];
    }
    
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect {
        // Drawing code
    }
    */
    
    @end
    
    

    使用

    #import "JWWavesAnimationViewController.h"
    #import "JWWavesAnimationView.h"
    #import <Masonry/Masonry.h>
    @interface JWWavesAnimationViewController ()
    
    @end
    
    @implementation JWWavesAnimationViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self.view setBackgroundColor:[UIColor lightGrayColor]];
        JWWavesAnimationView *waveView = [JWWavesAnimationView new];
        [waveView.layer setCornerRadius:50];
        [waveView setClipsToBounds:YES];
    
        [self.view addSubview:waveView];
        
        [waveView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.center.equalTo(self.view);
            make.width.height.equalTo(@100);
        }];
        
        [self.view layoutIfNeeded];
        [self.view setNeedsLayout];
        
        [waveView setUp];
        // Do any additional setup after loading the view.
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    /*
    #pragma mark - Navigation
    
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
    
    @end
    

    相关文章

      网友评论

        本文标题:iOS水波动画实现

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