在github上看到一個文字閃爍隨機漸入漸出的動畫效果其爵,跟著寫了一遍强胰,把自己對代碼的理解加上了注釋迅箩,發(fā)出來希望和大家共同學習侨歉,有理解錯的地方歡迎指正屋摇。
地址 : https://github.com/zipme/RQShineLabel
rqshinelabel.gif
#import <UIKit/UIKit.h>
@interface RQShineLabel: UILabel
//漸進時間
@property (assign, nonatomic, readwrite) CFTimeInterval shineDuration;
//漸出時間
@property (assign, nonatomic, readwrite) CFTimeInterval fadeoutDuration;
//開始動畫,默認為NO
@property (assign, nonatomic, readwrite, getter = isAutoStart) BOOL autoStart;
//結(jié)束動畫
@property (assign, nonatomic, readonly, getter = isShining) BOOL shining;
//是否看得到
@property (assign, nonatomic, readonly, getter = isVisible) BOOL visible;
//start the animation
- (void)shine;
- (void)shineWithCompletion:(void(^)())completion;
- (void)fadeOut;
- (void)fadeOutWithCompletion:(void(^)())completion;
#import "RQShineLabel.h"
@interface RQShineLabel()
@property (nonatomic, strong) NSMutableAttributedString *attributedString;
@property (nonatomic, strong) NSMutableArray *characterAnimationDurations;
@property (nonatomic, strong) NSMutableArray *characterAnimationDelays;
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (assign, nonatomic) CFTimeInterval beginTime;
@property (assign, nonatomic) CFTimeInterval endTime;
@property (assign, nonatomic, getter=isFadedOut) BOOL fadedOut;
@property (nonatomic, copy) void (^completion)();
@end
@implementation RQShineLabel
- (instancetype)init
{
self = [super init];
if (!self) {
return nil;
}
[self commonInit];
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
[self commonInit];
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (!self) {
return nil;
}
[self commonInit];
[self setText:self.text];
return self;
}
//公共部分
- (void)commonInit
{
//漸進
_shineDuration = 2.5;
//漸出
_fadeoutDuration = 2.5;
//開啟
_autoStart = NO;
//結(jié)束
_fadedOut = YES;
//文字顏色
self.textColor = [UIColor whiteColor];
_characterAnimationDurations = [NSMutableArray array];
_characterAnimationDelays = [NSMutableArray array];
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateAttributedString)];
_displayLink.paused = YES;
//添加到運行循環(huán) 模式是可以同時做兩件事
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
//顯示到window時調(diào)用
- (void)didMoveToWindow
{
if (nil != self.window && self.autoStart) {
[self shine];
}
}
- (void)setText:(NSString *)text
{
//創(chuàng)建字符屬性
self.attributedText = [[NSAttributedString alloc]initWithString:text];
}
- (void)setAttributedText:(NSAttributedString *)attributedText
{
//自定義字符屬性
self.attributedString = [self initiaAttributedStringFromAttributedString:attributedText];
//將自定義字符串賦給父類
[super setAttributedText:self.attributedString];
for (NSUInteger i = 0; i < attributedText.length; i ++) {
//隨機推遲字符
self.characterAnimationDelays[i] = @(arc4random_uniform(self.shineDuration / 2 * 100) / 100.0);
//還剩下的時間
CGFloat remain = self.shineDuration - [self.characterAnimationDelays[i] floatValue];
//隨機消失的時間
self.characterAnimationDurations[i] = @(arc4random_uniform(remain * 100) / 100.0);
}
}
//閃爍
- (void)shine
{
[self shineWithCompletion:NULL];
}
//閃爍 以及 回調(diào)
- (void)shineWithCompletion:(void (^)())completion
{
// self.isShining 返回的是 self.displayLink.isPaused的相反值
if (!self.isShining && self.isFadedOut) {
self.completion = completion;
// 每次閃爍開始幽邓,就把fadeout 設為 NO
self.fadedOut = NO;
[self startAnimationWithDuration:self.shineDuration];
}
}
- (void)startAnimationWithDuration:(CFTimeInterval)duration
{
//開始的時間 ---》當前時間
self.beginTime = CACurrentMediaTime();
//結(jié)束的時間 ---》當前時間 + 2.5
self.endTime = self.beginTime + self.shineDuration;
//動畫是否暫停 ---》NO ---》 動畫開始
self.displayLink.paused = NO;
}
//淡出
- (void)fadeOut
{
[self fadeOutWithCompletion:NULL];
}
// 再點擊屏幕后炮温,(BOOL)isVisible 的返回值為 YES的時候調(diào)用
// 初始化顯示完全(更新字符狀態(tài))self.displayLink.isPaused --》YES
- (void)fadeOutWithCompletion:(void (^)())completion
{
// 非閃爍 and 非動畫時間
if (!self.isShining &&!self.isFadedOut) {
//執(zhí)行BLOCK
self.completion = completion;
//淡出狀態(tài)
self.fadedOut = YES;
//淡出時間 self.displayLink.isPaused --》NO --》動畫開始
[self startAnimationWithDuration:self.fadeoutDuration];
}
}
- (BOOL)isShining
{
//沒暫停的時候就閃爍
return !self.displayLink.isPaused;
}
- (BOOL)isVisible
{
//沒淡出的時候 就看得見
return NO == self.isFadedOut;
}
//更新字符屬性
- (void)updateAttributedString
{
//到現(xiàn)在的時間
CFTimeInterval now = CACurrentMediaTime();
for (NSUInteger i = 0; i < self.attributedString.length; i ++) {
//[NSCharacterSet whitespaceCharacterSet] 刪除首尾空格
//如果有當前字符 就返回YES
if ([[NSCharacterSet whitespaceAndNewlineCharacterSet] characterIsMember:[self.attributedString.string characterAtIndex:i]]) {
// 從這里,結(jié)束 本次循環(huán) ---》 跳出進入下次循環(huán)
continue;
}
//指定字符范圍執(zhí)行block設置屬性
[self.attributedString enumerateAttribute:NSForegroundColorAttributeName inRange:NSMakeRange(i, 1) options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {
//獲得當前字符的透明度
CGFloat currentAlpha = CGColorGetAlpha([(UIColor *)value CGColor]);
//更新透明度
//淡出并且透明度大于0||不在淡出透明度小于0||調(diào)用更新字符屬性的時間-動畫開始的時間>=當前字符的推遲時間
BOOL shouldUpdateAlpha = (self.isFadedOut && currentAlpha > 0) || (!self.isFadedOut && currentAlpha < 1) || (now - self.beginTime) >= [self.characterAnimationDelays[i] floatValue];
//如果沒值 直接返回
if (!shouldUpdateAlpha) {
return ;
}
//兩副動畫的間隔-推遲的時間/動畫隨機消失的時間
// now現(xiàn)在的時間不短增加牵舵,所以percent會增大柒啤,以至于每個字體的顏色透明度增大
// 大于1 作用等同于 1
// 刷新這個 方法 用的link 一分鐘60次刷新
CGFloat percentage = (now - self.beginTime - [self.characterAnimationDelays[i] floatValue]) / ([self.characterAnimationDurations[i] floatValue]);
//如果正在淡出
if (self.isFadedOut) {
percentage = 1 - percentage;
}
//獲取百分比的透明度
UIColor *color = [self.textColor colorWithAlphaComponent:percentage];
//將透明度賦值給當前字符
[self.attributedString addAttribute:NSForegroundColorAttributeName value:color range:range];
}];
}
// set賦值
[super setAttributedText:self.attributedString];
//如果調(diào)用更新字符的時間大于動畫結(jié)束的時間 動畫暫停
if (now > self.endTime){
self.displayLink.paused = YES;
//動畫結(jié)束時候調(diào)用block
if (self.completion) {
self.completion();
}
}
}
- (NSMutableAttributedString *)initiaAttributedStringFromAttributedString:(NSAttributedString *)attributedString
{
//將傳進來的自定義字符串轉(zhuǎn)換為可自定義字符串
NSMutableAttributedString *mutableAttributedString = [attributedString mutableCopy];
//文字透明度為0
UIColor *color = [self.textColor colorWithAlphaComponent:0];
//將透明度和字符串的范圍賦值給自定義
[mutableAttributedString addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, mutableAttributedString.length)];
return mutableAttributedString;
}
@end
個人覺得加以修改用作第一次啟動程序的動畫還是挺炫酷的