1. 程式人生 > >請叫我楠哥(活雷鋒),謝謝!

請叫我楠哥(活雷鋒),謝謝!

在網上看到一個水波紋效果,挺好玩的,搞了好久才弄好。

看程式碼好了

標頭檔案:

//

//  NNGame.h

//  總結事例分享

//

//  Created by nan on 2017/8/29.

//  Copyright © 2017 nan. All rights reserved.

//

#import <UIKit/UIKit.h>

@interface NNGame : UIView

@property (assign,nonatomic) CGFloat waveAmplitude; //波的高度,即波峰

@property (assign,nonatomic) CGFloat

waveSpeed;   //水波上升的速度

@property (assign,nonatomic) CGFloat percent;  //顏色繪製的高度百分比,及波浪上升的百分比

@end

實現類:

//

//  NNGame.m

//  總結事例分享

//

//  Created by nan on 2017/8/29.

//  Copyright © 2017 nan. All rights reserved.

//

#import "NNGame.h"

staticconstCGFloat kExtraHeight = 10;     // 保證水波波峰不被裁剪,增加部分額外的高度

@interface

NNGame()

@property (assign,nonatomic) CGFloat offxset;   //波的偏移量,用於設定波的移動效果

@property (nonatomic, strong) CADisplayLink *displayLink;    //執行緒的使用

@property (strong,nonatomic) CAShapeLayer *shape;     //波形圖的繪製,第一重

@property (strong,nonatomic) CAGradientLayer *gradientLayer;   //波形圖的顏色繪製,水波紋色彩繪製,第一重

@property

(assign,nonatomic) CGFloat speedx;   //波在x軸方向上的移動速度

@property (nonatomic, assign) CGFloat waveCycle;      // 波紋週期,T = 2π/ω

@property (assign,nonatomic) CGFloat waveStartY;  //水波紋Y軸的起始位置

@end

@implementation NNGame

- (instancetype)initWithFrame:(CGRect)frame{

CGRect rect = frame;

CGFloat min = frame.size.width > frame.size.height ? frame.size.height : frame.size.width;

    rect.size.height = min;

    rect.size.width = min;

self = [superinitWithFrame:rect];

if (self) {

        [selfdefalute];

        [selfsetBackgroundColor:[UIColorcolorWithRed:4 / 255.0 green:181 / 255.0 blue:108 / 255.0 alpha:1]];

//        self.clipsToBounds = YES;  //設定預設將超出父檢視的部分進行裁剪

    }

returnself;

}

/**

配置一些常量

 */

- (void) defalute{

_speedx = 0.2 / M_PI;    //設定移動速度

_offxset = 0;    //設定最開始的偏移量

_percent = 0.3;   //設定波浪上升的百分比

_waveAmplitude = 4.f //波峰預設為10

}

/**

設定該波形色彩layer的色彩佔比

 */

- (void) setLoactions{

NSInteger count = [self.gradientLayer.colorscount];

NSMutableArray *locations = [[NSMutableArrayalloc] init];

for (int i = 0; i < count; i ++) {

NSNumber *num = @(1.0/count + 1.0/count * i);

        [locations addObject:num];

    }

NSNumber *lastNum = @(1.0f);

    [locations addObject:lastNum];

_gradientLayer.locations = locations;

}

-(void) initLayer{

if (self.shape)

    {

        [self.shaperemoveFromSuperlayer];

self.shape = nil;

    }

self.shape = [CAShapeLayerlayer];

self.shape.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);

}

-(void) initGraditent:(CAGradientLayer *) layer shape:(CAShapeLayer *) shape colors:(NSArray*) colors{

if (layer)

    {

        [layer removeFromSuperlayer];

        layer = nil;

    }

    layer = [CAGradientLayerlayer];

    layer.colors = colors;

    layer.startPoint = CGPointMake(0.5, 0.5);

    layer.endPoint = CGPointMake(0.5,1);

    layer.frame = [selfgradientLayerFrame];

//當將self.shape做為self.gradientLayer的裁剪時,self.shape的路徑座標系是以self.gradientLayer的座標為準的

    [layer setMask:shape];

    [self.layeraddSublayer:layer];

}

- (void) setLayerConfig{

    [selfinitLayer];

    [selfinitGraditent:self.gradientLayershape:self.shapecolors:[selfdefaultColors]];

  }

- (void)drawRect:(CGRect)rect{

_waveStartY = CGRectGetHeight(self.frame) * (1-self.percent);  //預設波浪的起始

_waveCycle = 4 * M_PI / CGRectGetWidth(self.frame);

    [selfsetLayerConfig];

//設定成圓形

self.layer.cornerRadius = rect.size.width/2;

if (self.displayLink)

    {

        [self.displayLinkinvalidate];

self.displayLink = nil;

    }

self.displayLink = [CADisplayLinkdisplayLinkWithTarget:selfselector:@selector(setCurrentWave:)];

    [self.displayLinkaddToRunLoop:[NSRunLoopmainRunLoop] forMode:NSRunLoopCommonModes];

}

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

}

/**

獲取第一重浪的顏色陣列

 @return 返回顏色陣列

 */

- (NSArray *)defaultColors

{

// 預設的漸變色

UIColor *color0 = [UIColorcolorWithRed:164 / 255.0green:216 / 255.0blue:222 / 255.0alpha:1];

UIColor *color1 = [UIColorcolorWithRed:105 / 255.0green:192 / 255.0blue:154 / 255.0alpha:1];

NSArray *colors = @[(__bridgeid)color0.CGColor, (__bridgeid)color1.CGColor];

return colors;

}

- (CGMutablePathRef) drawSin:(CGFloat) offset{

CGMutablePathRef path = CGPathCreateMutable();

//設定起始位置

CGPathMoveToPoint(path, nil, 0, self.waveStartY);

CGFloat width = self.frame.size.width;

for (float x = 0; x <= width ; x++) {

CGFloat y2 = self.waveAmplitude * sin(self.waveCycle * x + offset+3*M_PI/4)  + self.waveAmplitude;

CGPathAddLineToPoint(path, nil, x, y2);

CGFloat y1 = self.waveAmplitude * sin(self.waveCycle/1.5 * x + offset+3*M_PI/4)  + self.waveAmplitude*1.2;

CGPathAddLineToPoint(path, nil, x, y1);

CGFloat y = self.waveAmplitude * sin(self.waveCycle/2 * x + offset)  + self.waveAmplitude*1.4;

CGPathAddLineToPoint(path, nil, x, y);

    }

CGPathAddLineToPoint(path, nil, width, self.frame.size.height);

CGPathAddLineToPoint(path, nil, 0, self.frame.size.height);

CGPathCloseSubpath(path);

self.shape.path = path;

CGPathRelease(path);

return path;

}

- (void)setCurrentWave:(CADisplayLink *)displayLink{

self.offxset = self.offxset + self.speedx;

    [selfdrawSin:self.offxset];

}

@end

實現效果圖: