带辉光效果的跑马灯

带辉光效果的跑马灯

带辉光效果的跑马灯

 

效果

带辉光效果的跑马灯

 

说明

并没有对代码进行封装,以后会在项目 Animationhttps://github.com/YouXianMing/Animations)里面进行集成,欢迎前去star。

 

源码

UIView+GlowView

//
//  UIView+GlowView.h
//  GlowView
//
//  Created by YouXianMing on 15/7/4.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface UIView (GlowView)

//
//                                     == 动画时间解析 ==
//
//  0.0 ------------- 0.0 ------------> glowOpacity [-------------] glowOpacity ------------> 0.0
//           T                 T                           T                          T
//           |                 |                           |                          |
//           |                 |                           |                          |
//           .                 .                           .                          .
//     hideDuration  glowAnimationDuration           glowDuration            glowAnimationDuration
//

#pragma mark - 设置辉光效果

/**
 *  辉光的颜色
 */
@property (nonatomic, strong) UIColor  *glowColor;

/**
 *  辉光的透明度
 */
@property (nonatomic, strong) NSNumber *glowOpacity;

/**
 *  辉光的阴影半径
 */
@property (nonatomic, strong) NSNumber *glowRadius;

#pragma mark - 设置辉光时间间隔

/**
 *  一次完整的辉光周期(从显示到透明或者从透明到显示),默认1s
 */
@property (nonatomic, strong) NSNumber *glowAnimationDuration;

/**
 *  保持辉光时间(不设置,默认为0.5s)
 */
@property (nonatomic, strong) NSNumber *glowDuration;

/**
 *  不显示辉光的周期(不设置默认为0.5s)
 */
@property (nonatomic, strong) NSNumber *hideDuration;

#pragma mark - 辉光相关操作

/**
 *  创建出辉光layer
 */
- (void)createGlowLayer;

/**
 *  插入辉光的layer
 */
- (void)insertGlowLayer;

/**
 *  移除辉光的layer
 */
- (void)removeGlowLayer;

/**
 *  显示辉光
 */
- (void)glowToshow;

/**
 *  隐藏辉光
 */
- (void)glowToHide;

/**
 *  开始循环辉光
 */
- (void)startGlowLoop;

@end

UIView+GlowView.h


//
//  UIView+GlowView.m
//  GlowView
//
//  Created by YouXianMing on 15/7/4.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import "UIView+GlowView.h"
#import <objc/runtime.h>

@interface UIView ()

@property (nonatomic, strong) CALayer           *glowLayer;
@property (nonatomic, strong) dispatch_source_t  dispatchSource;

@end

@implementation UIView (GlowView)

- (void)createGlowLayer {
    
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIBezierPath* path = [UIBezierPath bezierPathWithRect:self.bounds];
    [[self accessGlowColor] setFill];
    [path fillWithBlendMode:kCGBlendModeSourceAtop alpha:1.0];
    
    self.glowLayer               = [CALayer layer];
    self.glowLayer.frame         = self.bounds;
    self.glowLayer.contents      = (__bridge id)UIGraphicsGetImageFromCurrentImageContext().CGImage;
    self.glowLayer.opacity       = 0.f;
    self.glowLayer.shadowOffset  = CGSizeMake(0, 0);
    self.glowLayer.shadowOpacity = 1.f;
    
    UIGraphicsEndImageContext();
}

- (void)insertGlowLayer {
    
    if (self.glowLayer) {
        
        [self.layer addSublayer:self.glowLayer];
    }
}

- (void)removeGlowLayer {
    
    if (self.glowLayer) {
        
        [self.glowLayer removeFromSuperlayer];
    }
}

- (void)glowToshow {
    
    self.glowLayer.shadowColor   = [self accessGlowColor].CGColor;
    self.glowLayer.shadowRadius  = [self accessGlowRadius].floatValue;
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    animation.fromValue         = @(0.f);
    animation.toValue           = [self accessGlowOpacity];
    self.glowLayer.opacity      = [self accessGlowOpacity].floatValue;
    animation.duration          = [self accessAnimationDuration].floatValue;
    
    [self.glowLayer addAnimation:animation forKey:nil];
}

- (void)glowToHide {
    
    self.glowLayer.shadowColor   = [self accessGlowColor].CGColor;
    self.glowLayer.shadowRadius  = [self accessGlowRadius].floatValue;
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    animation.fromValue         = [self accessGlowOpacity];
    animation.toValue           = @(0.f);
    self.glowLayer.opacity      = 0.f;
    animation.duration          = [self accessAnimationDuration].floatValue;
    
    [self.glowLayer addAnimation:animation forKey:nil];
}

- (void)startGlowLoop {
    
    if (self.dispatchSource == nil) {
        
        CGFloat seconds      = [self accessAnimationDuration].floatValue * 2 + [self accessGlowDuration].floatValue + [self accessHideDuration].floatValue;
        CGFloat delaySeconds = [self accessAnimationDuration].floatValue + [self accessGlowDuration].floatValue;
        
        self.dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
        dispatch_source_set_timer(self.dispatchSource, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC * seconds, 0);
        dispatch_source_set_event_handler(self.dispatchSource, ^{
            
            [self glowToshow];
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * delaySeconds), dispatch_get_main_queue(), ^{
                
                [self glowToHide];
            });
        });
        
        dispatch_resume(self.dispatchSource);
    }
}

#pragma mark - 处理数据越界问题

- (NSNumber *)accessGlowOpacity {
    
    if (self.glowOpacity) {
        
        if (self.glowOpacity.floatValue <= 0 || self.glowOpacity.floatValue > 1) {
            
            return @(0.8);
            
        } else {
            
            return self.glowOpacity;
        }
        
    } else {
        
        return @(0.8);
    }
}

- (NSNumber *)accessGlowDuration {
    
    if (self.glowDuration) {
        
        if (self.glowDuration.floatValue <= 0) {
            
            return @(0.5f);
            
        } else {
            
            return self.glowDuration;
        }
        
    } else {
        
        return @(0.5f);
    }
}

- (NSNumber *)accessHideDuration {
    
    if (self.hideDuration) {
        
        if (self.hideDuration.floatValue < 0) {
            
            return @(0.5);
            
        } else {
            
            return self.hideDuration;
        }
        
    } else {
        
        return @(0.5f);
    }
}

- (NSNumber *)accessAnimationDuration {
    
    if (self.glowAnimationDuration) {
        
        if (self.glowAnimationDuration.floatValue <= 0) {
            
            return @(1.f);
            
        } else {
            
            return self.glowAnimationDuration;
        }
        
    } else {
        
        return @(1.f);
    }
}

- (UIColor *)accessGlowColor {
    
    if (self.glowColor) {
        
        return self.glowColor;
        
    } else {
        
        return [UIColor redColor];
    }
}

- (NSNumber *)accessGlowRadius {
    
    if (self.glowRadius) {
        
        if (self.glowRadius.floatValue <= 0) {
            
            return @(2.f);
            
        } else {
            
            return self.glowRadius;
        }
        
    } else {
        
        return @(2.f);
    }
}

#pragma mark - runtime属性

NSString * const _recognizerDispatchSource = @"_recognizerDispatchSource";

- (void)setDispatchSource:(dispatch_source_t)dispatchSource {
    
    objc_setAssociatedObject(self, (__bridge const void *)(_recognizerDispatchSource), dispatchSource, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (dispatch_source_t)dispatchSource {
    
    return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerDispatchSource));
}

NSString * const _recognizerGlowColor = @"_recognizerGlowColor";

- (void)setGlowColor:(UIColor *)glowColor {
    
    objc_setAssociatedObject(self, (__bridge const void *)(_recognizerGlowColor), glowColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIColor *)glowColor {
    
    return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerGlowColor));
}

NSString * const _recognizerGlowOpacity = @"_recognizerGlowOpacity";

- (void)setGlowOpacity:(NSNumber *)glowOpacity {
    
    objc_setAssociatedObject(self, (__bridge const void *)(_recognizerGlowOpacity), glowOpacity, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSNumber *)glowOpacity {
    
    return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerGlowOpacity));
}

NSString * const _recognizerGlowRadius = @"_recognizerGlowRadius";

- (void)setGlowRadius:(NSNumber *)glowRadius {
    
    objc_setAssociatedObject(self, (__bridge const void *)(_recognizerGlowRadius), glowRadius, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSNumber *)glowRadius {
    
    return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerGlowRadius));
}

NSString * const _recognizerGlowAnimationDuration = @"_recognizerGlowAnimationDuration";

- (void)setGlowAnimationDuration:(NSNumber *)glowAnimationDuration {
    
    objc_setAssociatedObject(self, (__bridge const void *)(glowAnimationDuration), _recognizerGlowAnimationDuration, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSNumber *)glowAnimationDuration {
    
    return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerGlowAnimationDuration));
}

NSString * const _recognizerGlowDuration = @"_recognizerGlowDuration";

- (void)setGlowDuration:(NSNumber *)glowDuration {
    
    objc_setAssociatedObject(self, (__bridge const void *)(_recognizerGlowDuration), glowDuration, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSNumber *)glowDuration {
    
    return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerGlowDuration));
}

NSString * const _recognizerHideDuration = @"_recognizerHideDuration";

- (void)setHideDuration:(NSNumber *)hideDuration {
    
    objc_setAssociatedObject(self, (__bridge const void *)(_recognizerHideDuration), hideDuration, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSNumber *)hideDuration {
    
    return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerHideDuration));
}

NSString * const _recognizerGlowLayer = @"_recognizerGlowLayer";

- (void)setGlowLayer:(CALayer *)glowLayer {
    
    objc_setAssociatedObject(self, (__bridge const void *)(_recognizerGlowLayer), glowLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (CALayer *)glowLayer {
    
    return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerGlowLayer));
}

@end

UIView+GlowView.m

UIView+SetRect
//
//  UIView+SetRect.h
//  UIView
//
//  Created by YouXianMing on 16/1/29.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import <UIKit/UIKit.h>

/**
 *  UIScreen width.
 */
#define  Width   [UIScreen mainScreen].bounds.size.width

/**
 *  UIScreen height.
 */
#define  Height  [UIScreen mainScreen].bounds.size.height

/**
 *  Status bar height.
 */
#define  StatusBarHeight      20.f

/**
 *  Navigation bar height.
 */
#define  NavigationBarHeight  44.f

/**
 *  Tabbar height.
 */
#define  TabbarHeight         49.f

/**
 *  Status bar & navigation bar height.
 */
#define  StatusBarAndNavigationBarHeight   (20.f + 44.f)

/**
 *  iPhone4 or iPhone4s
 */
#define  iPhone4_4s     (Width == 320.f && Height == 480.f ? YES : NO)

/**
 *  iPhone5 or iPhone5s
 */
#define  iPhone5_5s     (Width == 320.f && Height == 568.f ? YES : NO)

/**
 *  iPhone6 or iPhone6s
 */
#define  iPhone6_6s     (Width == 375.f && Height == 667.f ? YES : NO)

/**
 *  iPhone6Plus or iPhone6sPlus
 */
#define  iPhone6_6sPlus (Width == 414.f && Height == 736.f ? YES : NO)

@interface UIView (SetRect)

/*----------------------
 * Absolute coordinate *
 ----------------------*/

@property (nonatomic) CGPoint viewOrigin;
@property (nonatomic) CGSize  viewSize;

@property (nonatomic) CGFloat x;
@property (nonatomic) CGFloat y;
@property (nonatomic) CGFloat width;
@property (nonatomic) CGFloat height;

@property (nonatomic) CGFloat top;
@property (nonatomic) CGFloat bottom;
@property (nonatomic) CGFloat left;
@property (nonatomic) CGFloat right;

@property (nonatomic) CGFloat centerX;
@property (nonatomic) CGFloat centerY;

/*----------------------
 * Relative coordinate *
 ----------------------*/

@property (nonatomic, readonly) CGFloat middleX;
@property (nonatomic, readonly) CGFloat middleY;
@property (nonatomic, readonly) CGPoint middlePoint;

@end

UIView+SetRect.h


//
//  UIView+SetRect.m
//  UIView
//
//  Created by YouXianMing on 16/1/29.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "UIView+SetRect.h"

@implementation UIView (SetRect)

- (CGPoint)viewOrigin {
    
    return self.frame.origin;
}

- (void)setViewOrigin:(CGPoint)viewOrigin {
    
    CGRect newFrame = self.frame;
    newFrame.origin = viewOrigin;
    self.frame      = newFrame;
}

- (CGSize)viewSize {
    
    return self.frame.size;
}

- (void)setViewSize:(CGSize)viewSize {
    
    CGRect newFrame = self.frame;
    newFrame.size   = viewSize;
    self.frame      = newFrame;
}

- (CGFloat)x {
    
    return self.frame.origin.x;
}

- (void)setX:(CGFloat)x {
    
    CGRect newFrame   = self.frame;
    newFrame.origin.x = x;
    self.frame        = newFrame;
}

- (CGFloat)y {
    
    return self.frame.origin.y;
}

- (void)setY:(CGFloat)y {
    
    CGRect newFrame   = self.frame;
    newFrame.origin.y = y;
    self.frame        = newFrame;
}

- (CGFloat)width {
    
    return CGRectGetWidth(self.bounds);
}

- (void)setWidth:(CGFloat)width {
    
    CGRect newFrame     = self.frame;
    newFrame.size.width = width;
    self.frame          = newFrame;
}

- (CGFloat)height {
    
    return CGRectGetHeight(self.bounds);
}

- (void)setHeight:(CGFloat)height {
    
    CGRect newFrame      = self.frame;
    newFrame.size.height = height;
    self.frame           = newFrame;
}

- (CGFloat)top {
    
    return self.frame.origin.y;
}

- (void)setTop:(CGFloat)top {
    
    CGRect newFrame   = self.frame;
    newFrame.origin.y = top;
    self.frame        = newFrame;
}

- (CGFloat)bottom {
    
    return self.frame.origin.y + self.frame.size.height;
}

- (void)setBottom:(CGFloat)bottom {
    
    CGRect newFrame   = self.frame;
    newFrame.origin.y = bottom - self.frame.size.height;
    self.frame        = newFrame;
}

- (CGFloat)left {
    
    return self.frame.origin.x;
}

- (void)setLeft:(CGFloat)left {
    
    CGRect newFrame   = self.frame;
    newFrame.origin.x = left;
    self.frame        = newFrame;
}

- (CGFloat)right {
    
    return self.frame.origin.x + self.frame.size.width;
}

- (void)setRight:(CGFloat)right {
    
    CGRect newFrame   = self.frame;
    newFrame.origin.x = right - self.frame.size.width;
    self.frame        = newFrame;
}

- (CGFloat)centerX {
    
    return self.center.x;
}

- (void)setCenterX:(CGFloat)centerX {
    
    CGPoint newCenter = self.center;
    newCenter.x       = centerX;
    self.center       = newCenter;
}

- (CGFloat)centerY {
    
    return self.center.y;
}

- (void)setCenterY:(CGFloat)centerY {
    
    CGPoint newCenter = self.center;
    newCenter.y       = centerY;
    self.center       = newCenter;
}

- (CGFloat)middleX {
    
    return CGRectGetWidth(self.bounds) / 2.f;
}

- (CGFloat)middleY {
    
    return CGRectGetHeight(self.bounds) / 2.f;
}

- (CGPoint)middlePoint {
    
    return CGPointMake(CGRectGetWidth(self.bounds) / 2.f, CGRectGetHeight(self.bounds) / 2.f);
}

@end

UIView+SetRect.m

NSString+LabelWidthAndHeight
//
//  NSString+LabelWidthAndHeight.h
//  ZiPeiYi
//
//  Created by YouXianMing on 15/12/9.
//  Copyright © 2015年 YouXianMing. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface NSString (LabelWidthAndHeight)

/**
 *  Get the string's height with the fixed width.
 *
 *  @param attribute String's attribute, eg. attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:18.f]}
 *  @param width     Fixed width.
 *
 *  @return String's height.
 */
- (CGFloat)heightWithStringAttribute:(NSDictionary <NSString *, id> *)attribute fixedWidth:(CGFloat)width;

/**
 *  Get the string's width.
 *
 *  @param attribute String's attribute, eg. attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:18.f]}
 *
 *  @return String's width.
 */
- (CGFloat)widthWithStringAttribute:(NSDictionary <NSString *, id> *)attribute;

/**
 *  Get a line of text height.
 *
 *  @param attribute String's attribute, eg. attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:18.f]}
 *
 *  @return String's width.
 */
+ (CGFloat)aLineOfTextHeightWithStringAttribute:(NSDictionary <NSString *, id> *)attribute;

@end

NSString+LabelWidthAndHeight.h


//
//  NSString+LabelWidthAndHeight.m
//  ZiPeiYi
//
//  Created by YouXianMing on 15/12/9.
//  Copyright © 2015年 YouXianMing. All rights reserved.
//

#import "NSString+LabelWidthAndHeight.h"

@implementation NSString (LabelWidthAndHeight)

- (CGFloat)heightWithStringAttribute:(NSDictionary <NSString *, id> *)attribute fixedWidth:(CGFloat)width {
    
    NSParameterAssert(attribute);
    
    CGFloat height = 0;
    
    if (self.length) {
        
        CGRect rect = [self boundingRectWithSize:CGSizeMake(width, MAXFLOAT)
                                         options:NSStringDrawingTruncatesLastVisibleLine |NSStringDrawingUsesLineFragmentOrigin |
                       NSStringDrawingUsesFontLeading
                                      attributes:attribute
                                         context:nil];
        
        height = rect.size.height;
    }
    
    return height;
}

- (CGFloat)widthWithStringAttribute:(NSDictionary <NSString *, id> *)attribute {
    
    NSParameterAssert(attribute);
    
    CGFloat width = 0;
    
    if (self.length) {
        
        CGRect rect = [self boundingRectWithSize:CGSizeMake(MAXFLOAT, 0)
                                         options:NSStringDrawingTruncatesLastVisibleLine |NSStringDrawingUsesLineFragmentOrigin |
                       NSStringDrawingUsesFontLeading
                                      attributes:attribute
                                         context:nil];
        
        width = rect.size.width;
    }
    
    return width;
}

+ (CGFloat)aLineOfTextHeightWithStringAttribute:(NSDictionary <NSString *, id> *)attribute {
    
    CGFloat height = 0;
    CGRect rect    = [@"One" boundingRectWithSize:CGSizeMake(200, MAXFLOAT)
                                          options:NSStringDrawingTruncatesLastVisibleLine |NSStringDrawingUsesLineFragmentOrigin |
                      NSStringDrawingUsesFontLeading
                                       attributes:attribute
                                          context:nil];
    
    height = rect.size.height;
    return height;
}

@end

NSString+LabelWidthAndHeight.m

ViewController.m
//
//  ViewController.m
//  UILabel
//
//  Created by YouXianMing on 16/4/13.
//  Copyright © 2016年 YouXianMing. All rights reserved.
//

#import "ViewController.h"
#import "UIView+SetRect.h"
#import "UIView+GlowView.h"
#import "NSString+LabelWidthAndHeight.h"

@interface ViewController () <UIGestureRecognizerDelegate>

@property (nonatomic, strong) UIView  *contentView;
@property (nonatomic, strong) UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    self.contentView                   = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 250.f, 20)];
    self.contentView.layer.borderWidth = 0.5f;
    self.contentView.layer.masksToBounds = YES;
    self.contentView.layer.borderColor = [[UIColor grayColor] colorWithAlphaComponent:0.25f].CGColor;
    self.contentView.center            = self.view.center;
    [self.view addSubview:self.contentView];
    
    NSString *string = @"Copyright © 2016 YouXianMing. All rights reserved.";
    CGFloat   width  = [string widthWithStringAttribute:@{NSFontAttributeName : [UIFont fontWithName:@"Heiti SC" size:14.f]}];
    self.label       = [[UILabel alloc] initWithFrame:CGRectMake(self.contentView.width, 0, width, self.contentView.height)];
    self.label.font  = [UIFont fontWithName:@"Heiti SC" size:14.f];
    self.label.text  = string;
    [self.contentView addSubview:self.label];
    
    [self doAnimation];
    
    // Start glow.
    self.label.glowRadius            = @(1.f);
    self.label.glowOpacity           = @(1.f);
    self.label.glowColor             = [[UIColor cyanColor] colorWithAlphaComponent:0.5f];
    self.label.glowDuration          = @(1.f);
    self.label.hideDuration          = @(3.f);
    self.label.glowAnimationDuration = @(2.f);
    [self.label createGlowLayer];
    [self.label insertGlowLayer];
    [self.label startGlowLoop];
    
    UIPanGestureRecognizer *tapGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureEvent:)];
    tapGesture.delegate                = self;
    [self.contentView addGestureRecognizer:tapGesture];
}

- (void)doAnimation {
    
    CGPoint       fromPoint = CGPointMake(self.contentView.width + self.label.width / 2.f, self.contentView.height / 2.f);
    UIBezierPath *movePath  = [UIBezierPath bezierPath];
    [movePath moveToPoint:fromPoint];
    [movePath addLineToPoint:CGPointMake(-self.label.width / 2, self.contentView.height / 2.f)];
    
    CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    moveAnimation.path                 = movePath.CGPath;
    moveAnimation.removedOnCompletion  = YES;
    moveAnimation.duration             = 8.f;
    moveAnimation.delegate             = self;
    [self.label.layer addAnimation:moveAnimation forKey:nil];
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    
    if (flag) {
        
        [self doAnimation];
    }
}

- (void)pauseLayer:(CALayer*)layer {
    
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed               = 0.0;
    layer.timeOffset          = pausedTime;
}

- (void)resumeLayer:(CALayer*)layer {
    
    CFTimeInterval pausedTime     = layer.timeOffset;
    layer.speed                   = 1.0;
    layer.timeOffset              = 0.0;
    layer.beginTime               = 0.0;
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    layer.beginTime               = timeSincePause;
}

- (void)tapGestureEvent:(UIPanGestureRecognizer *)tapGesture {
    
    if (tapGesture.state == UIGestureRecognizerStateBegan) {
        
        NSLog(@"拖拽");
        [self pauseLayer:self.label.layer];
        
    } else if (tapGesture.state == UIGestureRecognizerStateEnded) {
        
        NSLog(@"释放");
        [self resumeLayer:self.label.layer];
    }
}

@end

细节

暂停CALayer的动画以及恢复CALayer的动画

带辉光效果的跑马灯

用了贝塞尔曲线的Path动画来实现重复移动的效果

带辉光效果的跑马灯

上一篇:Unicode编码解码在线转换工具


下一篇:Android应用开发提高系列(4)——Android动态加载(上)——加载未安装APK中的类