zoukankan      html  css  js  c++  java
  • iOS之UI--辉光动画

    前言:学习来自YouXianMing老师的博客:《辉光UIView的category 》以及YouXianMing老师的github源码:《 GlowView

         而我个人考虑到分类的二次拓展性(或者是再一次拓展)不是特别好,所以将YouXianMing老师的用分类拓展的辉光动画,改写成一个继承CALayer的可拓展的普通类。

       一方面,也是作为自我训练编码,对辉光UIView的实现所使用到的上下文绘制、核心动画、GCD中的定时器以及Runtime动态添加属性等知识进一步的熟练运用和提高。

         个人经验不足,也许观点片面,读者尽量指出,我不会介意的。嘻嘻。

    先展示效果图:

    源码下载地址:https://github.com/HeYang123456789/UIView

    源码:

     1 //
     2 //  GlowLayer.h
     3 //  GlowView
     4 //
     5 //  Created by HEYANG on 16/1/30.
     6 //  Copyright © 2016年 HeYang. All rights reserved.
     7 //
     8 
     9 #import <UIKit/UIKit.h>
    10 
    11 //                                     == 动画时间解析 ==
    12 //
    13 //  0.0 ----------- 0.0 ------------> glowOpacity [---------------] glowOpacity ------------> 0.0
    14 //           T                T                           T                           T
    15 //           |                |                           |                           |
    16 //           |                |                           |                           |
    17 //           .                .                           .                           .
    18 //     hideDuration   animationDuration              glowDuration              animationDuration
    19 //
    20 
    21 /**
    22  *  需要考虑的参数
    23  *  
    24  *  需要考虑的逻辑
    25  *      1.数值越界问题,通过懒加载
    26  *      2.动画时间的安排(看前面的动画时间的解析)
    27  *
    28  *  需要对外公开的接口
    29  */
    30 
    31 
    32 @interface GlowLayer : CALayer
    33 
    34 #pragma mark - 对外公开的属性
    35 
    36 #pragma mark 设置辉光效果
    37 /** 辉光的阴影半径 */
    38 @property (nonatomic,strong)NSNumber *glowRadius;
    39 /** 辉光的透明度 */
    40 @property (nonatomic,strong)NSNumber *glowOpacity;
    41 
    42 #pragma mark 设置辉光的时间
    43 /** 保持辉光的时间,默认设置为0.5f */
    44 @property (nonatomic,strong)NSNumber *glowDuration;
    45 /** 不显示辉光的时间,默认设置为0.5f */
    46 @property (nonatomic,strong)NSNumber *hideDuration;
    47 /** 辉光的变化时间,从明到暗或者是从暗到明,默认设置为1.f */
    48 @property (nonatomic,strong)NSNumber *glowAnimationDuration;
    49 
    50 
    51 #pragma mark - 对外公开的接口
    52 
    53 /** 在原始的View上创建出辉光layer */
    54 -(void)createGlowLayerWithOriginView:(UIView*)originView glowColor:(UIColor*)glowColor;
    55 
    56 /** 显示辉光 */
    57 -(void)showGLowLayer;
    58 
    59 /** 隐藏辉光 */
    60 -(void)hideGlowLayer;
    61 
    62 /** 开始循环辉光动画 */
    63 -(void)startGlowAnimation;
    64 
    65 /** 暂停辉光动画 */
    66 -(void)pauseGlowAnimation;
    67 
    68 /** 重启辉光动画 */
    69 -(void)reStareGlowAnimation;
    70 
    71 @end
    72 
    73 @interface UIView (GlowViews)
    74 
    75 /** GlowLayer */
    76 @property (nonatomic,strong)GlowLayer *glowLayer;
    77 
    78 
    79 /** 创建GlowLayer,默认辉光颜色为红色 */
    80 -(void)addGlowLayer;
    81 /** 创建GlowLayer,需要设置辉光颜色 */
    82 -(void)addGlowLayerWithGlowColor:(UIColor*)glowColor;
    83 
    84 /** 插入辉光 */
    85 -(void)insertGlowLayerToSuperlayer;
    86 
    87 /** 完全移除GLowLayer */
    88 -(void)removeGlowLayerFromSuperlayer;
    89 @end
      1 //
      2 //  GlowLayer.m
      3 //  GlowView
      4 //
      5 //  Created by HEYANG on 16/1/30.
      6 //  Copyright © 2016年 HeYang. All rights reserved.
      7 //
      8 
      9 #import "GlowLayer.h"
     10 
     11 @interface GlowLayer ()
     12 
     13 /** 辉光的颜色 */
     14 @property (nonatomic,strong)UIColor *glowColor;
     15 
     16 /** 需要添加辉光效果的View ,注意这里用的是weak,而不是strong */
     17 @property (nonatomic,weak)UIView *addedGlowView;
     18 
     19 /** dispatch_source_t */
     20 @property (nonatomic,strong)dispatch_source_t timer;
     21 @end
     22 
     23 @implementation GlowLayer
     24 
     25 #pragma mark - 创建辉光
     26 
     27 // 遗留了一个先后顺序的问题,
     28 /** 在原始的View上创建出辉光layer */
     29 -(void)createGlowLayerWithOriginView:(UIView*)originView glowColor:(UIColor*)glowColor{
     30     self.glowColor = glowColor;
     31     // 创建一个图形上下文 参数:CGSize size:上下文的尺寸 BOOL opaque是否不透明 CGFloat scale缩放因子
     32     UIGraphicsBeginImageContextWithOptions(originView.bounds.size, NO, [UIScreen mainScreen].scale);
     33     // 通过get函数得到当前图形上下文,然后将origingView上的图形渲染到这个图形上下文上
     34     [originView.layer renderInContext:UIGraphicsGetCurrentContext()];
     35     // 创建贝塞尔曲线
     36     UIBezierPath *path = [UIBezierPath bezierPathWithRect:originView.bounds];
     37     // 设置贝塞尔取消绘制的颜色
     38     [self.glowColor setFill];//这里还是需要懒加载
     39     // 设置贝塞尔曲线绘制模式
     40     [path fillWithBlendMode:kCGBlendModeSourceAtop alpha:1];
     41     
     42     
     43     // 设置self(GlowLayer)初始状态
     44     self.frame = originView.bounds;
     45     // 至少要在设置好当前frame值之后,然后添加图形上下文的Image
     46     // 获得当前图形上下文的图形,然后赋值给CALayer的constraints
     47     self.contents = (__bridge id _Nullable)(UIGraphicsGetImageFromCurrentImageContext().CGImage);
     48 
     49     // 阴影设置不透明,其他的设置为透明
     50     self.opacity = 0.f;
     51     self.shadowOpacity = 1.f;
     52     // 阴影偏移量为(0,0)
     53     self.shadowOffset = CGSizeMake(0, 0);
     54     
     55     
     56     // 关闭图形上下文
     57     UIGraphicsEndImageContext();
     58     
     59     // 强引用指向这个原来的View
     60     self.addedGlowView = originView;
     61 }
     62 
     63 
     64 
     65 #pragma mark - 显示和隐藏辉光
     66 
     67 /** 显示辉光 */
     68 -(void)showGLowLayer{
     69     // 设置阴影初始效果
     70     self.shadowColor = self.glowColor.CGColor;
     71     self.shadowRadius = self.glowRadius.floatValue;
     72     
     73     
     74     CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
     75     animation.fromValue = @(0);
     76     animation.toValue = self.glowOpacity;
     77     animation.duration = self.glowAnimationDuration.floatValue;
     78     // 设置最终值
     79     self.opacity = self.glowOpacity.floatValue;
     80     
     81     [self addAnimation:animation forKey:nil];
     82 }
     83 
     84 /** 隐藏辉光 */
     85 -(void)hideGlowLayer{
     86     self.shadowColor = self.glowColor.CGColor;
     87     self.shadowRadius = self.glowRadius.floatValue;
     88     
     89     CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
     90     animation.fromValue = self.glowOpacity;
     91     animation.toValue = @(0);
     92     animation.duration = self.glowAnimationDuration.floatValue;
     93     // 设置最终值
     94     self.opacity = 0;
     95     
     96     [self addAnimation:animation forKey:nil];
     97 }
     98 
     99 #pragma mark - 循环显示和隐藏辉光
    100 
    101 /** 开始循环辉光动画 */
    102 -(void)startGlowAnimation{
    103     CGFloat cycleTime = self.glowAnimationDuration.floatValue * 2
    104     + self.glowDuration.floatValue + self.hideDuration.floatValue;
    105     CGFloat delayTime = self.glowAnimationDuration.floatValue + self.glowDuration.floatValue;
    106     
    107     _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    108     dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, cycleTime * NSEC_PER_SEC, 0);
    109     dispatch_source_set_event_handler(_timer, ^{
    110         [self showGLowLayer];
    111         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    112             [self hideGlowLayer];
    113         });
    114     });
    115     dispatch_resume(_timer);
    116 }
    117 /** 暂停辉光动画 */
    118 -(void)pauseGlowAnimation{
    119     [self removeFromSuperlayer];
    120 }
    121 /** 重启辉光动画 */
    122 -(void)reStareGlowAnimation{
    123     [self.addedGlowView.layer addSublayer:self];
    124     [self startGlowAnimation];
    125 }
    126 
    127 #pragma mark - 懒加载辉光的效果,同时处理数据越界问题
    128 #pragma mark duration 辉光时间
    129 -(NSNumber *)glowDuration{
    130     if (!_glowDuration || _glowDuration.floatValue < 0) {
    131         _glowDuration = @(0.5f);
    132     }
    133     return _glowDuration;
    134 }
    135 -(NSNumber *)hideDuration{
    136     if (!_hideDuration || _hideDuration.floatValue < 0) {
    137         _hideDuration = @(0.5);
    138     }
    139     return _hideDuration;
    140 }
    141 -(NSNumber *)glowAnimationDuration{
    142     if (!_glowDuration || _glowDuration.floatValue < 0) {
    143         _glowDuration = @(1.f);
    144     }
    145     return _glowDuration;
    146 }
    147 #pragma mark 辉光颜色
    148 -(UIColor *)glowColor{
    149     if (!_glowColor) {
    150         _glowColor = [UIColor redColor];
    151     }
    152     return _glowColor;
    153 }
    154 #pragma mark 辉光半径
    155 -(NSNumber *)glowRadius{
    156     if (!_glowRadius || _glowRadius.floatValue <= 0) {
    157         _glowRadius = @(2.f);
    158     }
    159     return _glowRadius;
    160 }
    161 #pragma mark 辉光透明度
    162 -(NSNumber *)glowOpacity{
    163     if (!_glowOpacity || _glowOpacity.floatValue <= 0) {
    164         _glowOpacity = @(0.8);
    165     }
    166     return _glowOpacity;
    167 }
    168 @end
    169 
    170 #import <objc/runtime.h>
    171 
    172 @implementation UIView (GlowViews)
    173 
    174 /** 创建GlowLayer,默认辉光颜色为红色 */
    175 -(void)addGlowLayer{
    176     [self addGlowLayerWithGlowColor:nil];
    177 }
    178 /** 创建GlowLayer,需要设置辉光颜色 */
    179 -(void)addGlowLayerWithGlowColor:(UIColor*)glowColor{
    180     if (self.glowLayer == nil) {
    181         self.glowLayer = [[GlowLayer alloc] init];
    182     }
    183     [self.glowLayer createGlowLayerWithOriginView:self glowColor:glowColor];
    184     [self insertGlowLayerToSuperlayer];
    185 }
    186 #pragma mark - 插入和移除辉光
    187 
    188 /** 插入辉光 */
    189 -(void)insertGlowLayerToSuperlayer{
    190     if (self.glowLayer == nil) {
    191         self.glowLayer = [[GlowLayer alloc] init];
    192     }
    193     [self.layer addSublayer:self.glowLayer];
    194 }
    195 
    196 
    197 /** 移除辉光 */
    198 -(void)removeGlowLayerFromSuperlayer{
    199     [self.glowLayer removeFromSuperlayer];
    200     self.glowLayer = nil;
    201 }
    202 
    203 #pragma mark - Runtime动态添加属性
    204 NSString * const _recognizerGlowLayer = @"_recognizerGlowLayer";
    205 -(void)setGlowLayer:(GlowLayer *)glowLayer{
    206     objc_setAssociatedObject(self, (__bridge const void *)(_recognizerGlowLayer), glowLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    207 }
    208 -(GlowLayer *)glowLayer{
    209     return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerGlowLayer));
    210 }
    211 
    212 
    213 @end

    使用实例:

     转载注明出处:http://www.cnblogs.com/goodboy-heyang/p/5172807.html,尊重劳动成果哦。

  • 相关阅读:
    暑假D16 T3 密道(数位DP? 打表找规律)
    暑假D16 T2 无聊 (深搜)
    暑假D14 T3 cruise(SDOI2015 寻宝游戏)(虚树+set)
    Django url
    http协议
    host文件以及host的作用
    用socket写一个简单的服务器
    python中*args **kwargs
    javascript 判断对像是否相等
    html input标签详解
  • 原文地址:https://www.cnblogs.com/goodboy-heyang/p/5172807.html
Copyright © 2011-2022 走看看