iOS双波浪效果(CAShaperLayer,一般人我不告诉他)

贴代码之前我们先了解一下CAShaperLayer吧
首先这是一个遮罩类,这个东西是画出来的,是一个闭合的曲线,我门可以用这个类来对view来进行各种变形,闭合的区域外都是透明的,根据这个特性,我们就可以来浪了

补充知识:首先你要知道啥事正弦函数,就是sin,上过高中的,听过课的应该都知道这玩应是干啥的,就一个起点是(0,0)的浪,依稀的记得好像还有个圆一转,就出来了,法科!忘记了,自行google。

正弦波浪公式:y=Asin(ωx+φ)+k
-A——振幅,当物体作轨迹符合正弦曲线的直线往复运动时,其值为行程的1/2
-ω——角速度, 控制正弦周期(单位角度内震动的次数)
-φ——初相,x=0时的相位;反映在坐标系上则为图像的左右移动
-k——偏距,反映在坐标系上则为图像的上移或下移

--------------------------脱裤子,入正题--------------------------

我写的是一个视图

需要的类

CAShapeLayer:遮罩
CADisplayLink :这个东西跟定时器一样,不过这个东西是在target没刷新1帧才执行一次,所以NSTimer 用起来是不准确的

需要的属性

@property (nonatomic, strong) CAShapeLayer *waveShapeLayerA; //?<  遮罩
@property (nonatomic, strong) CAShapeLayer *waveShapeLayerB; //?< 另外一个遮罩
@property (nonatomic, strong) UIColor *waveColor;            //?< 颜色
@property (nonatomic, strong) CADisplayLink *displayLink;    //?< 定时器
@property (nonatomic, assign) CGFloat offsetX;               //?< A相位
@property (nonatomic, assign) CGFloat offsetXB;              //?< B相位
@property (nonatomic, assign) CGFloat waveWidth;             //?< 浪的宽度
@property (nonatomic, assign) CGFloat waveAmplitude;         //?< 振幅
@property (nonatomic, strong) UIView *back;                  //?< 另外一个颜色的视图
//下面这两个我方.h里面了
@property (nonatomic, assign) CGFloat waveHeight;
@property (nonatomic, assign) CGFloat waveSpeed;
(void)wave;

初始化变量

- (void)layoutSubviews
{
    _offsetX    = 0;
    _offsetXB   = M_PI/2.0;  //让第2个layer移动1/4个周期
    _waveSpeed  = 0.03;
    _waveHeight = 30;
    _waveWidth  = self.frame.size.width;
    _waveAmplitude = 10;
}

让它动

这里创建了两个CAShaperLayer,一个给self 另一个给加在self上的另外一个视图

- (void)wave {
    /*
     *创建两个layer
     */
    self.waveColor = [UIColor colorWithRed:((arc4random() % 255)/244.0) green:((arc4random() % 255)/244.0) blue:((arc4random() % 255)/244.0) alpha:0.3];
    self.waveShapeLayerA = [CAShapeLayer layer];
    self.waveShapeLayerA.fillColor = self.waveColor.CGColor;
    [self.layer addSublayer:self.waveShapeLayerA];
    
    
    _back = [[UIView alloc]initWithFrame:self.bounds];
    [self addSubview:_back];
    self.waveShapeLayerB = [CAShapeLayer layer];
    self.waveShapeLayerB.fillColor = [UIColor blueColor].CGColor;
    [self.back.layer addSublayer:self.waveShapeLayerB];
    
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(getCurrentWave)];
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

核心的东西

这里主要是公式,然后通过x得到所有Y的点绘制成一个闭合的曲线,需要两个,因为我们是两个浪

- (void)getCurrentWave {
    //offsetX决定x位置,如果想搞明白可以多试几次
    self.offsetX += self.waveSpeed;
    //声明第一条波曲线的路径
    CGMutablePathRef path = CGPathCreateMutable();
    //设置起始点
    CGPathMoveToPoint(path, nil, 0, self.waveHeight);
    
    CGFloat y = 0.f;
    //第一个波纹的公式
    for (float x = 0.f; x <= self.waveWidth ; x++) {
        y = self.waveAmplitude * sin((300 / self.waveWidth) * (x * M_PI / 180) - self.offsetX) + self.waveHeight;
        CGPathAddLineToPoint(path, nil, x, y);
        x++;
    }
    //把绘图信息添加到路径里
    CGPathAddLineToPoint(path, nil, self.waveWidth, self.frame.size.height);
    CGPathAddLineToPoint(path, nil, 0, self.frame.size.height);
    //结束绘图信息
    CGPathCloseSubpath(path);
    
    self.waveShapeLayerA.path = path;
    //释放绘图路径
    CGPathRelease(path);
    
    /*
     *  第二个
     */
    self.offsetXB += self.waveSpeed;
    CGMutablePathRef pathT = CGPathCreateMutable();
    CGPathMoveToPoint(pathT, nil, 0, self.waveHeight+100);
    
    CGFloat yT = 0.f;
    for (float x = 0.f; x <= self.waveWidth ; x++) {
        yT = self.waveAmplitude * sin((300 / self.waveWidth) * (x * M_PI / 180) - self.offsetXB) + self.waveHeight;
        CGPathAddLineToPoint(pathT, nil, x, yT);
    }
    CGPathAddLineToPoint(pathT, nil, self.waveWidth, self.frame.size.height);
    CGPathAddLineToPoint(pathT, nil, 0, self.frame.size.height);
    CGPathCloseSubpath(pathT);
    self.waveShapeLayerB.path = pathT;
    CGPathRelease(pathT);
}

基本完成

稍作修饰,就可以出锅了!这里我用了两个slider 分别控制高度 和速度,别的变量也可以。

- (void)viewDidLoad {
    [super viewDidLoad];
    _wave = [[WaveView alloc]initWithFrame:CGRectMake(50, 400, 300, 300)];
    [self.view addSubview:_wave];
    _wave.layer.masksToBounds = YES;
    _wave.layer.cornerRadius = 150;
    [_wave wave];
    _wave.backgroundColor = [UIColor colorWithRed:((arc4random() % 255)/244.0) green:((arc4random() % 255)/244.0) blue:((arc4random() % 255)/244.0) alpha:0.3];
}
- (IBAction)change:(UISlider *)sender {
    CGFloat value = (sender.value * 150);
    _wave.waveHeight = value;
}
- (IBAction)speed:(UISlider *)sender {
    CGFloat value = (sender.value * 0.1);
    _wave.waveSpeed = value;
}
iOS双波浪效果(CAShaperLayer,一般人我不告诉他)_第1张图片
Paste_Image.png

结构层次

我们可以看到,两个view分别用layer来实现波浪,这样就双波浪了(好像废话)


iOS双波浪效果(CAShaperLayer,一般人我不告诉他)_第2张图片
Paste_Image.png

你可能感兴趣的:(iOS双波浪效果(CAShaperLayer,一般人我不告诉他))