博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
带辉光效果的跑马灯
阅读量:7104 次
发布时间:2019-06-28

本文共 21740 字,大约阅读时间需要 72 分钟。

带辉光效果的跑马灯

 

效果

 

说明

并没有对代码进行封装,以后会在项目 Animation()里面进行集成,欢迎前去star。

 

源码

UIView+GlowView

////  UIView+GlowView.h//  GlowView////  Created by YouXianMing on 15/7/4.//  Copyright (c) 2015年 YouXianMing. All rights reserved.//#import 
@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 
@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 
/** * 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 
#import
@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
*)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
*)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
*)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 
*)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
*)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
*)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 () 
@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动画来实现重复移动的效果

 

转载地址:http://owchl.baihongyu.com/

你可能感兴趣的文章
CAS SSO单点登录框架学习
查看>>
好书推荐——《启动大脑》
查看>>
网络流24题 -No.17 运输问题
查看>>
MySQL数据库的主从复制简单学习使用
查看>>
kprobe原理与实现笔记
查看>>
sql语句优化
查看>>
Topological Sorting
查看>>
神经网络
查看>>
WINDOWS之入侵痕迹清理总结
查看>>
把一个project相关的jar放到project的lib文件夹中
查看>>
Sublime Text2 Jsformat自定义使用之代码折叠方式修改
查看>>
OpenMP 中的线程任务调度
查看>>
用Qt写软件系列四:定制个性化系统托盘菜单
查看>>
Asp.net 4.0,首次请求目录下的文件时响应很慢
查看>>
hdu-------(1848)Fibonacci again and again(sg函数版的尼姆博弈)
查看>>
GridView编辑删除操作
查看>>
iOS程序的启动图片图标规范
查看>>
动画 -- 按钮 -- 左右晃动
查看>>
mysql+ssh整合样例,附源代码下载
查看>>
WWF3XOML方式创建和启动工作流 <第十篇>
查看>>