这次对水波纹控件进行了封装,便于大家使用。下面是效果图。(上层有个蒙版图,截个图给大家参考下,不过这个蒙版图的颜色可以自己渲染,只要把imageColor传进来就可以啦,蒙版的话就是那个image了,下面这个是我用的蒙版图)
下面是控件的源码
头文件:
//
// 总结事例分享
//
// Created by nan on 2017/8/29.
// Copyright © 2017年 nan. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface NNWaterView : UIView
@property (assign,nonatomic) CGFloat speedx; //波浪的移动速度
@property (strong,nonatomic) UIColor *boradColor; //外围边的颜色
@property (strong,nonatomic) NSMutableArray *locations; //色层占的比例
@property (strong,nonatomic) NSArray *colors; //颜色层
@property (assign,nonatomic) CGFloat boradWidth; //外围边
@property (assign,nonatomic) CGFloat waveAmplitude; //波的高度,即波峰
@property (assign,nonatomic) CGFloat speedy; //水波上升的速度
@property (nonatomic, assign) CGFloat waveCycle; // 波纹周期,T = 2π/ω,即波纹的宽度
@property (assign,nonatomic) CGFloat wavePercent; //颜色绘制的高度百分比,及波浪上升的百分比
@property (strong,nonatomic) UIImage *image; //中间的蒙版
@property (strong,nonatomic) UIColor *imageColor; //中间蒙版的颜色
@property (strong,nonatomic) UIColor *labelColor; //百分比的颜色
/**
资源释放
*/
- (void) invalidate;
@end
.m文件
//
// 总结事例分享
//
// Created by nan on 2017/8/29.
// Copyright © 2017年 nan. All rights reserved.
//
#import "NNWaterView.h"
static const CGFloat kExtraHeight = 10; // 保证水波波峰不被裁剪,增加部分额外的高度
@interface NNWaterView()
@property (assign,nonatomic) CGFloat offxset; //波的偏移量,用于设置波的移动效果
@property (strong, nonatomic) CADisplayLink *displayLink; //线程的使用
@property (strong,nonatomic) CAShapeLayer *shape; //波形图的绘制,第一重
@property (strong,nonatomic) CAGradientLayer *gradientLayer; //波形图的颜色绘制,水波纹色彩绘制,第一重
@property (assign,nonatomic) CGFloat waveStartY; //水波纹Y轴的起始位置
@property (assign,nonatomic) CGFloat percent; //水波纹的百分比
@property (strong,nonatomic) UIImageView *imageView; //顶层蒙版
@property (strong,nonatomic) UILabel *labelPercent; //百分比
@property (assign,nonatomic) BOOL initWaveStartY; //是否初始化过水波纹的初始Y值
@end
@implementation NNWaterView
#pragma mark 懒加载和属性设置
- (UILabel *)labelPercent{
if (!_labelPercent) {
_labelPercent = [[UILabel alloc] init];
}
return _labelPercent;
}
- (void)setLabelColor:(UIColor *)labelColor{
_labelColor = labelColor;
self.labelPercent.textColor = labelColor;
}
- (UIImageView *)imageView{
if (!_imageView) {
_imageView = [[UIImageView alloc] init];
}
return _imageView;
}
- (void)setImage:(UIImage *)image{
_image = image;
self.imageView.image = [self imageWithColor:image];
}
/**
设置周期是该宽的几倍
@param waveCycle <#waveCycle description#>
*/
- (void)setWaveCycle:(CGFloat)waveCycle{
_waveCycle = _waveCycle * waveCycle;
}
/**
设置波的百分比
@param wavePercent 百分比
*/
- (void)setWavePercent:(CGFloat)wavePercent{
_wavePercent = wavePercent;
self.labelPercent.text = [[NSString stringWithFormat:@"%d",(int)(_wavePercent * 100)] stringByAppendingString:@"%"];
if (!_initWaveStartY) {
_initWaveStartY = YES;
_waveStartY = self.frame.size.height * wavePercent;
}
[UIView animateWithDuration:1 animations:^{
self.gradientLayer.frame = [self gradientLayerFrame:self.frame];
}];
}
/**
设置边框的宽度
@param boradWidth 边框宽度
*/
- (void)setBoradWidth:(CGFloat)boradWidth{
_boradWidth = boradWidth;
self.layer.borderWidth = boradWidth;
}
/**
设置边框的颜色
@param boradColor 边框的颜色
*/
- (void)setBoradColor:(UIColor *)boradColor{
_boradColor = boradColor;
self.layer.borderColor = boradColor.CGColor;
}
#pragma mark 初始化
- (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 = [super initWithFrame:rect];
if (self) {
[self defalute:rect];
[self initUI:rect];
}
return self;
}
/**
初始化UI控件
@param frame 视图的尺寸大小
*/
- (void) initUI:(CGRect) frame{
self.layer.cornerRadius = frame.size.width/2;
[self initLayer];
[self initGraditent:frame];
[self initCADisplayLink];
[self setBackgroundColor:[UIColor colorWithRed:4 / 255.0 green:181 / 255.0 blue:108 / 255.0 alpha:1]];
self.clipsToBounds = YES; //设置默认将超出父视图的部分进行裁剪
self.imageView.bounds = self.bounds;
self.imageView.center = self.center;
self.labelPercent.bounds = self.bounds;
self.labelPercent.font = [UIFont systemFontOfSize:frame.size.width / 5];
self.labelPercent.textAlignment = NSTextAlignmentCenter;
self.labelPercent.center = self.center;
self.labelPercent.textColor = [UIColor whiteColor];
[self addSubview:self.imageView];
[self addSubview:self.labelPercent];
}
/**
配置一些常量
*/
- (void) defalute:(CGRect) frame{
_initWaveStartY = NO;
_speedx = 0.2 / M_PI; //设置移动速度
_offxset = 0; //设置最开始的偏移量
_percent = 0; //设置波浪上升的百分比
_wavePercent = 0; //设置默认值
_speedy = 0.15;
_waveStartY = _waveAmplitude;
_waveCycle = 3 * M_PI / CGRectGetWidth(self.frame);
_waveAmplitude = 0.05 * frame.size.height;
}
#pragma mark layer的初始化
/**
初始化CAShapeLayer
*/
-(void) initLayer{
if (self.shape)
{
[self.shape removeFromSuperlayer];
self.shape = nil;
}
self.shape = [CAShapeLayer layer];
self.shape.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
}
/**
初始化CAGradientLayer
*/
-(void) initGraditent:(CGRect) rect{
if (self.gradientLayer)
{
[self.gradientLayer removeFromSuperlayer];
self.gradientLayer = nil;
}
self.gradientLayer = [CAGradientLayer layer];
if (self.colors) {
self.gradientLayer.colors = self.colors;
}else{
self.gradientLayer.colors = [self defaultColors];
}
self.gradientLayer.startPoint = CGPointMake(0.5, 0.5);
self.gradientLayer.endPoint = CGPointMake(0.5,1);
self.gradientLayer.frame = [self gradientLayerFrame:rect];
//当将self.shape做为self.gradientLayer的裁剪时,self.shape的路径坐标系是以self.gradientLayer的坐标为准的
[self.gradientLayer setMask:self.shape];
[self.layer addSublayer:self.gradientLayer];
}
/**
初始化CADisplayLink
*/
- (void)initCADisplayLink{
if (self.displayLink)
{
[self.displayLink invalidate];
self.displayLink = nil;
}
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(setCurrentWave:)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
/**
设置该波形色彩layer的色彩占比,即CAGradientLayer的色彩占比
*/
- (void) setLoactions{
if (self.locations) {
_gradientLayer.locations = self.locations;
}else{
NSInteger count = [self.gradientLayer.colors count];
NSMutableArray *locations = [[NSMutableArray alloc] 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;
}
}
#pragma mark 获取CAGradientLayer尺寸和颜色
/**
计算CAGradientLayer的尺寸大小
@return 返回CAGradientLayer的尺寸大小
*/
- (CGRect)gradientLayerFrame:(CGRect) rect
{
// gradientLayer在上升完成之后的frame值,如果gradientLayer在上升过程中不断变化frame值会导致一开始绘制卡顿,所以只进行一次赋值
//NSLog(@"self.percent = %f",self.percent);
CGFloat gradientLayerHeight = CGRectGetHeight(rect) * self.wavePercent + kExtraHeight;
if (gradientLayerHeight > CGRectGetHeight(rect))
{
gradientLayerHeight = CGRectGetHeight(rect);
}
CGRect frame = CGRectMake(0, CGRectGetHeight(rect) - gradientLayerHeight, CGRectGetWidth(self.frame), gradientLayerHeight);
return frame;
}
/**
获取第一重浪的颜色数组
@return 返回颜色数组
*/
- (NSArray *)defaultColors
{
// 默认的渐变色
UIColor *color0 = [UIColor colorWithRed:164 / 255.0 green:216 / 255.0 blue:222 / 255.0 alpha:1];
UIColor *color1 = [UIColor colorWithRed:105 / 255.0 green:192 / 255.0 blue:154 / 255.0 alpha:1];
NSArray *colors = @[(__bridge id)color0.CGColor, (__bridge id)color1.CGColor];
return colors;
}
#pragma mark 绘制波形图
- (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++) {
//振幅*sin(角速度*x+偏移量)+初始y值
CGFloat y2 = self.waveAmplitude * sin(self.waveCycle * x + offset+3*M_PI/4) + self.waveStartY;
CGPathAddLineToPoint(path, nil, x, y2);
CGFloat y1 = self.waveAmplitude * sin(self.waveCycle/1.5 * x + offset+3*M_PI/4) + self.waveStartY*1.2;
CGPathAddLineToPoint(path, nil, x, y1);
CGFloat y = self.waveAmplitude * sin(self.waveCycle/2 * x + offset) + self.waveStartY*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;
[self drawSin:self.offxset];
if (self.waveStartY > self.waveAmplitude) {
self.waveStartY = self.waveStartY - self.speedy;
}
}
#pragma mark 工具方法
//改变图片颜色
- (UIImage *)imageWithColor:(UIImage *)image
{
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
CGContextClipToMask(context, rect, image.CGImage);
if (self.imageColor) {
[self.imageColor setFill];
}else{
[[UIColor colorWithRed:4 / 255.0 green:181 / 255.0 blue:108 / 255.0 alpha:1] setFill];
}
CGContextFillRect(context, rect);
UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
/**
移除刷屏线程
*/
- (void) invalidate{
if(self.displayLink) {
[self.displayLink invalidate];
self.displayLink = nil;
}
}
@end
请叫我活雷锋,谢谢,哈哈哈。