請叫我楠哥(活雷鋒),謝謝!
在網上看到一個水波紋效果,挺好玩的,搞了好久才弄好。
看程式碼好了
標頭檔案:
//
// 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
@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
@property (assign,nonatomic) CGFloat offxset; //波的偏移量,用於設定波的移動效果
@property (nonatomic, strong) CADisplayLink *displayLink; //執行緒的使用
@property (strong,nonatomic) CAShapeLayer *shape; //波形圖的繪製,第一重
@property (strong,nonatomic) CAGradientLayer *gradientLayer; //波形圖的顏色繪製,水波紋色彩繪製,第一重
@property
@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
實現效果圖: