34

iOS 弹幕效果

 5 years ago
source link: http://www.cocoachina.com/ios/20180711/24127.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

项目中视频直播有个弹幕功能,网上也有很多弹幕的demo,之前忙于项目进度,没有细致研究其中是如何实现的。如今闲暇之余,就研究一下其中的实现原理。

网上的弹幕demo,简单的是用label作为一条弹幕,然后控制label的动画,但是label显示样式单一,做不了图文混排的功能,所以就有了这篇文章。

最基本的特点:

1、文字越长的弹幕,跑的越快,弹幕的速度和文字长度有关系.
 
2、弹幕不相互碰撞(开始结束均不碰撞)。
 
3、如果有数据,会一条接着一跳的播放。

需要考虑的方面:

1、重用或者释放;
 
2、暂停和继续;
 
3、load新数据;
 
4、碰撞问题;

原理分析

  1. 检测模型数组里面所有的模型,是否可以发射 如果可以,直接发射 dataSource为数据源

  2. 遍历所有的弹道,在每个弹道里面,进行检测(检测开始碰撞 检测结束碰撞)

  3. 确定可以发射,把弹幕视图加到弹道背景里面。

QJfqArq.png!web

ziuQnef.png!web

当弹幕移动到屏幕外的时候,移除弹幕。

FzEJzez.png!web

技术实现~~

以下是部分核心代码,完整 Demo 参见这里.

- (BOOL)checkBoomAndBiuWith:(id

  
   
 )model {
 
   

CGFloat danmakuH = self.frame.size.height / kDandaoCount ;
// 遍历所有的弹道,在每个弹道里面,进行检测(检测开始碰撞 检测结束碰撞)
for ( int i = 0 ; i < kDandaoCount; i++) {
//1.获取该弹道的绝对等待时间
NSTimeInterval waitTime = [ self.laneWaitTimeArr[i] doubleValue];
if (waitTime > 0.0) {
continue;
}
//2.绝对等待时间没有 暂时可以发射 需要判断 是否与前一个弹幕视图产生碰撞
UIView * danmakuView = [ self.delegate danmakuViewWithModel:model];
NSTimeInterval leftTime = [ self.laneLeftTimeArr[i] doubleValue];
// 速度 = (弹幕视图的宽度 + 弹幕背景的宽度)/liveTime
double speed = ( danmakuView.frame.size.width + self.frame.size.width) / model.liveTime;
double distance = leftTime * speed;
if (distance > self.frame.size.width) {
continue;
}

[ self.danmakuViewArr addObject:danmakuView];

//重置数据
// 距离/秒 = 速度v
self.laneWaitTimeArr[i] = @(danmakuView.frame.size.width / speed);
self.laneLeftTimeArr[i] = @(model.liveTime);

//3.弹幕肯定可以发射
//3.1 先把弹幕视图,加到弹幕背景里面
CGRect frame = danmakuView.frame;
frame.origin = CGPointMake( self.frame.size.width, danmakuH * i);
danmakuView.frame = frame;
[ self addSubview:danmakuView];

[ UIView animateWithDuration:model.liveTime delay: 0 options: UIViewAnimationOptionCurveLinear animations:^{
CGRect frame = danmakuView.frame;
frame.origin.x = - danmakuView.frame.size.width;
danmakuView.frame = frame;
} completion:^( BOOL finished) {
[danmakuView removeFromSuperview];
[ self.danmakuViewArr removeObject:danmakuView];
}];

return YES;
}

return NO;
}

作者:翀鹰女孩

链接:https://www.jianshu.com/p/f37ef9e49dea


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK