说明
1.大多数弹幕都采用时间来控制弹幕,能够很好的适配在播放器、或者是一些对除了弹幕动画外,其他动画很少的项目中运行。而当除了弹幕动画以外,还存在更多动画时,就会导致动画冲突,而使弹幕停留不前,内存消耗巨大。故结合实际,简单写下此弹幕
2.此动画采用CABasicAnimation动画,与大多数动画不同采用时间来控制弹幕的走向有所不同。但是目前无法控制弹幕的停留,实际我所接触的项目也没有这个需求。
3.存在问题点,或者说是可优化点在于创建时默认初始化多个弹幕通道,但可能程序运行中,有些通道并不能得到有效的利用,如何在利用到的时候在进行初始化,有时间我在提交一个版本。
弹幕展示
处理弹幕消息
1.我的思路是在处理接受到弹幕到时候,从上往下依次判断所创建的通道是否畅通,若找到畅通的通道时,进行数据渲染,开始动画。当所创建的通道全部被占用时,默认将消息保存在内存中,并按时间0.2秒循环查找是否有畅通通道。当内存中没有未处理的消息时,将定时器释放,代码如下
- (void)sendMessage:(NSMutableAttributedString *)attributedString
withSpseed:(int)spseed
withImage:(NSString *)imagePath
withInsets:(UIEdgeInsets)insets {
if (!_isaccording) {
if (!_cacheInfoArr) {
_cacheInfoArr = [[NSMutableArray alloc] init];
}
ZHModel *model = [[ZHModel alloc] init];
model.attributedString = attributedString;
model.imagePath = imagePath;
model.spseed = spseed;
model.textInsets = insets;
[_cacheInfoArr addObject:model];
return;
}
if (_cacheInfoArr && _cacheInfoArr.count > 0) {
//别急,先处理当前缓存信息
ZHModel *model = [[ZHModel alloc]init];
model.attributedString = attributedString;
model.spseed = spseed;
model.imagePath = imagePath;
model.textInsets = insets;
[_cacheInfoArr addObject:model];
return;
}
//是否查找到通道
for (int i = 0; i < _countChannel; i++) {
ZHLabel *label = [self viewWithTag:ZH_Label_tag + I];
NSLog(@"curr channel %d unblocked = %d",i,label.unblocked);
if (label.unblocked == YES) {
[label updateAttributed:attributedString
withSpseed:spseed
withImage:imagePath
withInsets:insets];
return;
}
}
//处理未找到通道时动作
NSLog(@"creat succeed");
if (!_cacheInfoArr) {
_cacheInfoArr = [[NSMutableArray alloc] init];
}
ZHModel *model = [[ZHModel alloc] init];
model.attributedString = attributedString;
model.imagePath = imagePath;
model.spseed = spseed;
model.textInsets = insets;
[_cacheInfoArr addObject:model];
if (!caCcheTime) {
caCcheTime = [NSTimer scheduledTimerWithTimeInterval:0.2
target:self
selector:@selector(cacheTimeFunction)
userInfo:nil
repeats:YES];
}
}
- (void)cacheTimeFunction{
ZHModel *model = [_cacheInfoArr firstObject];
for (int i = 0; i < _countChannel; i++) {
ZHLabel *label = [self viewWithTag:ZH_Label_tag + I];
if (label.unblocked == YES) {
[label updateAttributed:model.attributedString
withSpseed:model.spseed
withImage:model.imagePath
withInsets:model.textInsets];
[_cacheInfoArr removeObjectAtIndex:0];
if (_cacheInfoArr.count == 0) {
//清空集合,停止时间循环
_cacheInfoArr = nil;
[self stopCacheTime];
NSLog(@"clean succeed");
}
return;
}
}
}
2.动画采用CABasicAnimation动画,并监听动画是否完成
- (void)startAnimationandLabel:(ZHLabel *)label{
CGFloat customLabwith = label.frame.size.width;
int time = (ZH_ANIMATION_WIDTH + customLabwith*2 + 10)/self.spseed;
CGFloat left_P = - (customLabwith/2 - 10);
CGPoint center = CGPointMake(ZH_ANIMATION_WIDTH + customLabwith/2 + 5, label.center.y);
CGPoint finishPoint = CGPointMake(left_P, label.center.y);
CABasicAnimation *animationgo = [CABasicAnimation animationWithKeyPath:@"position"];
animationgo.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animationgo.duration = time;
animationgo.repeatCount = 1;
animationgo.delegate = self;
animationgo.removedOnCompletion = NO;
animationgo.beginTime = CACurrentMediaTime();
animationgo.fromValue = [NSValue valueWithCGPoint:center];
animationgo.toValue = [NSValue valueWithCGPoint:finishPoint];
[label.layer addAnimation:animationgo forKey:@"label"];
_label = label;
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if (anim == [_label.layer animationForKey:@"label"]) {
[_label.layer removeAnimationForKey:@"label"];
_label.unblocked = YES;
}
}
介绍
给我们项目打一个广告吧,欢迎去AppStore搜索下载"欢乐狼人杀",有什么想法,或者看法,也可能联系我,欢迎大神点评