iOS 仿百度外卖-个人中心(头像波浪效果)

来源:互联网 发布:淘宝培训靠谱吗 编辑:程序博客网 时间:2024/05/16 15:24

今天带来的是仿百度外卖个人中心的波浪效果,先看下效果图吧

一,项目里用到了两个类:

一个是CADisplayLink类,我用它取代了NSTimer,首先,它是利用刷帧和屏幕频率一样来重绘渲染页面,也就是说每次屏幕刷新的时候就会调用它的响应方法(屏幕一般一秒刷新60次)在绘图中需要重绘时常用它来代替NSTimer,其次,因为NSTimer调度优先级比较低,并不会准时调用,做动画的话会有卡顿的感觉

另一个是CAShapeLayer类,它属于CALayer的子类,通常结合CGPath来绘制不规则矩形图形.

其优点:

    1.渲染效率高渲染快速。CAShapeLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多。

    2.高效使用内存。一个CAShapeLayer不需要像普通CALayer一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。

    3.不会被图层边界剪裁掉。一个CAShapeLayer可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer一样被剪裁掉。

    4.不会出现像素化。当你给CAShapeLayer3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。


 二,下面是功能的实现(直接使用就可以)

先自定义类,基于 UIView(WavesView)

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //  
  2. //  WavesView.h  
  3. //  仿百度外卖-个人中心(头像波浪效果)  
  4. //  
  5. //  Created by Amydom on 16/12/28.  
  6. //  Copyright © 2016年 Amydom. All rights reserved.  
  7. //  
  8.   
  9. #import <UIKit/UIKit.h>  
  10.   
  11. typedef void(^WavesBlock)(CGRect myFrame);  
  12.   
  13. @interface WavesView : UIView  
  14.   
  15. /** 
  16.  *  浪弯曲度 
  17.  */  
  18. @property (nonatomic, assign) CGFloat waveCurvature;  
  19. /** 
  20.  *  浪速 
  21.  */  
  22. @property (nonatomic, assign) CGFloat waveSpeed;  
  23. /** 
  24.  *  浪高 
  25.  */  
  26. @property (nonatomic, assign) CGFloat waveHeight;  
  27. /** 
  28.  *  实浪颜色 
  29.  */  
  30. @property (nonatomicstrongUIColor *realWaveColor;  
  31. /** 
  32.  *  遮罩浪颜色 
  33.  */  
  34. @property (nonatomicstrongUIColor *maskWaveColor;  
  35.   
  36. @property (nonatomiccopy) WavesBlock waveBlock;  
  37.   
  38. @property (nonatomic , assign)CGRect imageFrame;  
  39.   
  40.   
  41. - (void)stopWaveAnimation;  
  42.   
  43. - (void)startWaveAnimation;  
  44.   
  45. @end  

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //  
  2. //  WavesView.m  
  3. //  仿百度外卖-个人中心(头像波浪效果)  
  4. //  
  5. //  Created by Amydom on 16/12/28.  
  6. //  Copyright © 2016年 Amydom. All rights reserved.  
  7. //  
  8.   
  9. #import "WavesView.h"  
  10.   
  11. @interface WavesView ()  
  12.   
  13. /** 
  14.  *  定时器 
  15.     CADisplayLink:利用刷帧和屏幕频率一样来重绘渲染页面,也就是说每次屏幕刷新的时候就会调用它的响应方法(屏幕一般一秒刷新60次),在绘图中需要重绘时常用它来代替NSTimer,因为NSTimer调度优先级比较低,并不会准时调用,做动画的话会有卡顿的感觉 
  16.   
  17. */  
  18. @property (nonatomicstrongCADisplayLink *timer;  
  19. /** 
  20.  *  实浪动画 
  21.     CAShapeLayer:CALayer的子类,通常结合CGPath来绘制不规则矩形图形 
  22.     其优点: 
  23.     1.渲染效率高渲染快速。CAShapeLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多。 
  24.     2.高效使用内存。一个CAShapeLayer不需要像普通CALayer一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。 
  25.     3.不会被图层边界剪裁掉。一个CAShapeLayer可以在边界之外绘制。你的图层路径不会像在使用Core Graphics的普通CALayer一样被剪裁掉。 
  26.     4.不会出现像素化。当你给CAShapeLayer做3D变换时,它不像一个有寄宿图的普通图层一样变得像素化。 
  27.  
  28.  */  
  29. @property (nonatomicstrongCAShapeLayer *realWaveLayer;  
  30. /** 
  31.  *  遮罩浪动画 
  32.  */  
  33. @property (nonatomicstrongCAShapeLayer *maskWaveLayer;  
  34. /** 
  35.  *  <#Description#> 
  36.  */  
  37. @property (nonatomic, assign) CGFloat offset;  
  38.   
  39.   
  40. @end  
  41.   
  42. @implementation WavesView  
  43.   
  44. #pragma mark - 初始化  
  45.   
  46. - (instancetype)initWithFrame:(CGRect)frame  
  47. {  
  48.     self = [super initWithFrame:frame];  
  49.     if (self) {  
  50.         [self setUp];  
  51.     }  
  52.     return self;  
  53. }  
  54.   
  55. -(void)setUp{  
  56.       
  57.     //初始化  
  58.     self.waveSpeed = 0.5;  
  59.     self.waveCurvature = 1.5;  
  60.     self.waveHeight = 4;  
  61.     self.realWaveColor = [UIColor whiteColor];  
  62.     self.maskWaveColor = [[UIColor whiteColor] colorWithAlphaComponent:0.4];  
  63.       
  64.     [self.layer addSublayer:self.realWaveLayer];  
  65.     [self.layer addSublayer:self.maskWaveLayer];  
  66.       
  67.       
  68. }  
  69.   
  70. #pragma mark - lazyload  
  71.   
  72. - (CAShapeLayer *)realWaveLayer{  
  73.       
  74.     if (!_realWaveLayer) {  
  75.         _realWaveLayer = [CAShapeLayer layer];  
  76.         CGRect frame = self.bounds;  
  77.         frame.origin.y = frame.size.height-self.waveHeight;  
  78.         frame.size.height = self.waveHeight;  
  79.         _realWaveLayer.frame = frame;  
  80.         _realWaveLayer.fillColor = self.realWaveColor.CGColor;  
  81.   
  82.     }  
  83.       
  84.     return _realWaveLayer;  
  85.       
  86. }  
  87. - (CAShapeLayer *)maskWaveLayer{  
  88.       
  89.     if (!_maskWaveLayer) {  
  90.          _maskWaveLayer = [CAShapeLayer layer];  
  91.         CGRect frame = self.bounds;  
  92.         frame.origin.y = frame.size.height-self.waveHeight;  
  93.         frame.size.height = self.waveHeight;  
  94.         _maskWaveLayer.frame = frame;  
  95.         _maskWaveLayer.fillColor = self.maskWaveColor.CGColor;  
  96.           
  97.     }  
  98.     return _maskWaveLayer;  
  99.       
  100. }  
  101.   
  102. - (void)setWaveHeight:(CGFloat)waveHeight{  
  103.       
  104.     _waveHeight = waveHeight;  
  105.     CGRect frame = self.bounds;  
  106.     frame.origin.y = frame.size.height - self.waveHeight;  
  107.     frame.size.height = self.waveHeight;  
  108.     _realWaveLayer.frame =  _maskWaveLayer.frame =  frame;  
  109.       
  110. }  
  111. #pragma mark - 动画  
  112. - (void)startWaveAnimation{  
  113.       
  114.     self.timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(wave)];  
  115.     [self.timer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];  
  116.       
  117.       
  118. }  
  119.   
  120. - (void)stopWaveAnimation{  
  121.       
  122.     [self.timer invalidate];  
  123.     self.timer = nil;  
  124.       
  125.       
  126. }  
  127.   
  128. //描述路径,并用CAShapeLayer绘制出来  
  129. - (void)wave{  
  130.       
  131.     self.offset += self.waveSpeed;  
  132.       
  133.     //获取宽,高  
  134.     CGFloat width = CGRectGetWidth(self.frame);  
  135.     CGFloat height = self.waveHeight;  
  136.       
  137.     //真实波浪  
  138.     CGMutablePathRef realpath = CGPathCreateMutable();  
  139.     CGPathMoveToPoint(realpath, NULL0, height);  
  140.     CGFloat realY = 0.f;  
  141.       
  142.     //遮罩波浪  
  143.     CGMutablePathRef maskpath = CGPathCreateMutable();  
  144.     CGPathMoveToPoint(maskpath, NULL0, height);  
  145.     CGFloat maskY = 0.f;  
  146.       
  147.     for (CGFloat x = 0.f; x <= width; x++) {  
  148.           
  149.         realY = height * sinf(0.01 * self.waveCurvature * x + self.offset * 0.045);  
  150.         CGPathAddLineToPoint(realpath, NULL, x, realY);  
  151.         maskY = -realY;  
  152.         CGPathAddLineToPoint(maskpath, NULL, x, maskY);  
  153.   
  154.     }  
  155.     //变化的中间 Y 值  
  156.     CGFloat centX = self.bounds.size.width / 2;  
  157.     CGFloat centY = height * sinf(0.01 * self.waveCurvature * centX + self.offset * 0.045);  
  158.       
  159.     if (self.waveBlock) {  
  160.           
  161.         //修改头像view的高度  
  162.         CGRect iconFrame = self.imageFrame;  
  163.           
  164.         iconFrame.origin.y = CGRectGetHeight(self.frame)-CGRectGetHeight(self.imageFrame) + centY - self.waveHeight;  
  165.           
  166.         self.imageFrame = iconFrame;  
  167.           
  168.         self.waveBlock(self.imageFrame);  
  169.           
  170.     }  
  171.     //真实波浪  
  172.     CGPathAddLineToPoint(realpath, NULL, width, height);  
  173.     CGPathAddLineToPoint(realpath, NULL0, height);  
  174.     CGPathCloseSubpath(realpath);  
  175.       
  176.     //描述路径后利用CAShapeLayer类绘制不规则图形  
  177.     self.realWaveLayer.path = realpath;  
  178.     self.realWaveLayer.fillColor = self.realWaveColor.CGColor;  
  179.     CGPathRelease(realpath);  
  180.       
  181.     //遮罩波浪  
  182.     CGPathAddLineToPoint(maskpath, NULL, width, height);  
  183.     CGPathAddLineToPoint(maskpath, NULL0, height);  
  184.     CGPathCloseSubpath(maskpath);  
  185.       
  186.     //描述路径后利用CAShapeLayer类绘制不规则图形  
  187.     self.maskWaveLayer.path = maskpath;  
  188.     self.maskWaveLayer.fillColor = self.maskWaveColor.CGColor;  
  189.     CGPathRelease(maskpath);  
  190.   
  191.       
  192.       
  193. }  
  194.   
  195. @end  

然后是调用,这里就简单的说明下如何调用(在 viewController 里)

首先创建的头像的 image(我是通过懒加载创建的)

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. - (UIImageView *)iconImageView{  
  2.       
  3.     if (!_iconImageView) {  
  4.         _iconImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.WavesView.frame.size.width/2 - 3006060)];  
  5.         _iconImageView.layer.borderColor = [UIColor whiteColor].CGColor;  
  6.         _iconImageView.layer.borderWidth = 2;  
  7.         _iconImageView.layer.cornerRadius = 30;  
  8.     }  
  9.     return _iconImageView;  
  10. }  

然后创建 wavesView,并且把创建好的 image的 frame 传过去

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. - (void)viewDidLoad {  
  2.       
  3.     [super viewDidLoad];  
  4.     //创建对线  
  5.     self.WavesView = [[WavesView alloc]initWithFrame:CGRectMake(022self.view.frame.size.width150)];  
  6.       
  7.     self.WavesView.backgroundColor =[UIColor redColor];  
  8.       
  9.     [self.view addSubview:self.WavesView];  
  10.       
  11.     [_WavesView addSubview:self.iconImageView];  
  12.       
  13.     //这里把头像的 frame 传入到 wavesView里,让其通过 frame来计算该变量  
  14.      _WavesView.imageFrame = _iconImageView.frame;  
  15.     //防止循环引用  
  16.     __weak typeof(self)weakSelf = self;  
  17.       
  18.     _WavesView.waveBlock = ^(CGRect imageFrame){  
  19.         //修改头像view的frame(时时的通过 block 回调改变的 frame)  
  20.         weakSelf.iconImageView.frame = imageFrame;  
  21.           
  22.     };  
  23.     //开始执行  
  24.     [_WavesView startWaveAnimation];  
  25.       
  26. }  

到这里,波浪形动画就完成了.....大家没事可以多看看动画的实现,对于里面有些东西我也是比较模糊的状态,但是多看多谢,慢慢的你就会发现收获还是有的...




0 0