美文网首页
绘制波浪正弦曲线

绘制波浪正弦曲线

作者: C_HPY | 来源:发表于2018-08-08 19:20 被阅读57次

    iOS绘制波浪,具体来说就是结合CAShaperLayer、UIBezierPath进行一个高性能的绘制。前文已经说过这两者是如何可以进行高性能绘制,这里不再赘述。
    具体需要先了解正弦曲线的公式,初中数学,我给贴过来了。

    正弦曲线可表示为y=Asin(ωx+φ)+k,定义为函数y=Asin(ωx+φ)+k在直角坐标系上的图象,其中sin为正弦符号,x是直角坐标系x轴上的数值,y是在同一直角坐标系上函数对应的y值,k、ω和φ是常数(k、ω、φ∈R且ω≠0)
    A——振幅,当物体作轨迹符合正弦曲线的直线往复运动时,其值为行程的1/2。
    (ωx+φ)——相位,反映变量y所处的状态。
    φ——初相,x=0时的相位;反映在坐标系上则为图像的左右移动。
    k——偏距,反映在坐标系上则为图像的上移或下移。
    ω——角速度, 控制正弦周期(单位弧度内震动的次数)。

    先看效果吧,懒得录制gif了,静态图凑合看吧,有兴趣的可以下载demo查看。

    image.png

    封装了一个WaterWave的类,使用很简单:

    #import "ViewController.h"
    #import "WaterWave.h"
    
    @interface ViewController ()
    
    @property (weak, nonatomic) IBOutlet WaterWave *waveView;
    
    @end
    
    @implementation ViewController
    #pragma mark - event
    - (IBAction)startWave:(id)sender {
        [self. waveView startWave];
    }
    
    - (IBAction)pauseWave:(id)sender {
        [self.waveView pauseWave];
    }
    
    
    @end
    

    WaterWave类:

    #import <UIKit/UIKit.h>
    
    @interface WaterWave : UIView
    
    @property (nonatomic, strong, nullable)UIColor *waveColor;   // 波浪颜色
    
    /**
     default is 0.7   [0,1]
     */
    @property (nonatomic, assign)CGFloat percent;      // 波浪百分比
    
    - (void)startWave;
    
    - (void)pauseWave;
    
    - (void)removeWave;
    
    @end
    
    
    //
    //  WaterWave.m
    //  WaterWave
    //
    //  Created by wu on 2018/8/7.
    //  Copyright © 2018年 wu. All rights reserved.
    //
    
    #import "WaterWave.h"
    
    @interface WaterWave ()
    
    @property (nonatomic, strong) CADisplayLink *waveDisplayLink;
    @property (nonatomic, strong) CAShapeLayer *waveLayer;
    @property (nonatomic, assign) CGFloat waveAmplitude;           // 波纹振幅
    @property (nonatomic, assign) CGFloat waveCycle;               // 波纹周期
    @property (nonatomic, assign) CGFloat waveSpeed;               // 波纹速度
    @property (nonatomic, assign) CGFloat waveWidth;               // 波纹宽度
    @property (nonatomic, assign) CGFloat xOffset;                 // 正弦曲线的初相,反映出在x轴上的移动,
    @property (nonatomic, assign) CGFloat originWavePointY;
    
    @end
    
    @implementation WaterWave
    #pragma mark - init
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self setup];
            [self startWave];
        }
        return self;
    }
    
    - (instancetype)initWithCoder:(NSCoder *)aDecoder
    {
        self = [super initWithCoder:aDecoder];
        if (self) {
            [self setup];
            [self startWave];
        }
        return self;
    }
    
    - (void)setup
    {
        self.waveColor         = [UIColor cyanColor];
        self.percent           = 0.7;
        
        self.waveSpeed         = 0.1/M_PI;
        self.waveWidth         = CGRectGetWidth(self.frame);
        self.xOffset           = 0;
        self.waveAmplitude     = 15;
        self.originWavePointY  = CGRectGetHeight(self.frame) * (1-_percent);
        self.waveCycle         =  1.29 * M_PI / self.waveWidth;
    }
    
    #pragma mark - public
    - (void)startWave
    {
        if (!_waveLayer) {
            [self.layer addSublayer:self.waveLayer];
        }
        [self.waveDisplayLink setPaused:NO];
    }
    
    - (void)pauseWave
    {
        [self.waveDisplayLink setPaused:YES];
    }
    
    - (void)removeWave
    {
        [self.waveDisplayLink invalidate];
        [self.waveLayer removeFromSuperlayer];
    
        self.waveDisplayLink = nil;
        self.waveLayer       = nil;
    }
    
    - (void)setPercent:(CGFloat)percent
    {
        _percent = (percent >0 && percent <= 1) ? percent : _percent;
    }
    
    
    #pragma mark - event
    - (void)changeWave:(CADisplayLink *)displayLink
    {
        self.xOffset -= self.waveSpeed;
        
        UIBezierPath *sinPath = [UIBezierPath bezierPath];
        CGFloat sinY = self.originWavePointY;
        [sinPath moveToPoint:CGPointMake(0, sinY)];
        
        for (float x = 0.0f; x <= self.waveWidth; x++) {
            // 正弦波浪
            sinY = self.waveAmplitude * sin(self.waveCycle * x + self.xOffset) + self.originWavePointY;
            [sinPath addLineToPoint:CGPointMake(x, sinY)];
        }
        [sinPath addLineToPoint:CGPointMake(self.waveWidth, CGRectGetHeight(self.frame))];
        
        [sinPath addLineToPoint:CGPointMake(0, self.frame.size.height)];
        [sinPath closePath];
        
        self.waveLayer.path = sinPath.CGPath;
    }
    
    #pragma mark - getter
    - (CAShapeLayer *)waveLayer
    {
        if (!_waveLayer) {
            _waveLayer           = [CAShapeLayer layer];
            _waveLayer.fillColor = _waveColor.CGColor;
        }
        return _waveLayer;
    }
    
    - (CADisplayLink *)waveDisplayLink
    {
        if (!_waveDisplayLink) {
            _waveDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(changeWave:)];
            [_waveDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
        }
        return _waveDisplayLink;
    }
    @end
    
    

    有问题的可以一起沟通,也欢迎指正代码存在的错误和不严谨之处。

    相关文章

      网友评论

          本文标题:绘制波浪正弦曲线

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