赞
踩
效果图
该跑马灯完全通过CATextLayer 实现,轻量级,并且通过
系统的位移动画实现滚动效果,避免了使用displaylink造成的性能瓶颈,使用系统动画,系统自动做了很多性能优化,实现更好的性能,并使用遮罩实现展示范围的限定
,实现跑马灯效果
// // LBMarqueeLayer.m // TEXT // // Created by mac on 2024/4/28. // Copyright © 2024 刘博. All rights reserved. // #import "LBMarqueeLayer.h" @implementation LBMarqueeLayerConfig - (instancetype)init { self = [super init]; if (self) { self.velocity = 20; self.fontSize = 14; self.textColor = [UIColor darkGrayColor]; self.pauseDuration = 3; self.blankString = @" "; } return self; } @end @interface LBMarqueeLayer () <CAAnimationDelegate> @property (nonatomic, strong) CATextLayer *textLayer; @property (nonatomic, strong) CALayer *maskLayer; @property (nonatomic, strong) LBMarqueeLayerConfig *config; @property (nonatomic, strong) CABasicAnimation *animation; @end @implementation LBMarqueeLayer - (instancetype)initwithFrame:(CGRect)frame config:(LBMarqueeLayerConfig *)config { if ([super init]) { self.frame = frame; self.config = config; [self handleText]; [self addSublayer:self.textLayer]; } return self; } - (void)handleText { CGFloat width = [self.config.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:self.config .fontSize]}].width; if (width > CGRectGetWidth(self.bounds)) { NSString *content = [NSString stringWithFormat:@"%@%@%@", self.config.text, self.config.blankString, self.config.text]; NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:content attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:self.config.fontSize]}]; self.textLayer.string = attributedString; CGFloat width = [content sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:self.config .fontSize]}].width; self.textLayer.frame = CGRectMake(0, 0, width, CGRectGetHeight(self.bounds)); CGFloat toValue = [[NSString stringWithFormat:@"%@%@", self.config.text, self.config.blankString] sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:self.config .fontSize]}].width; self.animation.fromValue = @(0); self.animation.toValue = @(-toValue); self.animation.duration = toValue/self.config.velocity; [self.textLayer addAnimation:self.animation forKey:@"animation"]; self.masksToBounds = YES; } else { self.textLayer.string = self.config.text; } } #pragma mark - animationDelegate - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { if (flag) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.config.pauseDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.textLayer addAnimation:self.animation forKey:@"animation"]; }); } } #pragma mark - lazy load - (CATextLayer *)textLayer { if (!_textLayer) { _textLayer = [[CATextLayer alloc] init]; _textLayer.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame)); _textLayer.alignmentMode = kCAAlignmentLeft; _textLayer.fontSize = 14; _textLayer.foregroundColor = self.config.textColor.CGColor; } return _textLayer; } - (CALayer *)maskLayer { if (!_maskLayer) { _maskLayer = [[CALayer alloc] init]; _maskLayer.frame = self.bounds; } return _maskLayer; } - (CABasicAnimation *)animation { if (!_animation) { _animation = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"]; if (!self.config.hasPause) { _animation.repeatCount = NSIntegerMax; } _animation.delegate = self; } return _animation; } @end
调用
- (LBMarqueeLayer *)textLayer
{
if (!_textLayer) {
LBMarqueeLayerConfig *config = [[LBMarqueeLayerConfig alloc] init];
config.hasPause = YES;
config.pauseDuration = 3;
config.blankString = @" ";
config.text = @"这是一首非常好听的歌曲哈哈哈哈";
_textLayer = [[LBMarqueeLayer alloc] initwithFrame:CGRectMake(100, 100, 200, 50) config:config];
_textLayer.backgroundColor = [UIColor cyanColor].CGColor;
}
return _textLayer;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。