IOS 实现简单的弹幕功能
前言
简单实现弹幕功能,表跟我谈效率,但也有用队列控制同时弹的数量。
正文
代码实现:
letDANMAKU_SPEED:CGFloat=150//弹幕每秒移动速度
letDANMAKU_SPACE_TIME:NSTimeInterval=1//弹幕之间的时间间隔
letDANMAKU_MAX_ROW=3//最多同时弹幕行数
letdanmakuFont=UIFont.systemFontOfSize(18)//弹幕字体大小
varrowArray=Array<Array<Danmaku>>(count:3,repeatedValue:Array<Danmaku>())
vardanmakuQueue=NSOperationQueue()//队列
classDanmaku:NSObject{
varmsg:Msg
varview:UILabel?
varsize=CGSize(width:0,height:0)
varrow=0
varstartTime:NSDate?
varduration:NSTimeInterval=0
vardelay:NSTimeInterval=0
init(_msg:Msg,_row:Int,_delay:NSTimeInterval=0){
self.msg=msg
self.row=row
self.delay=delay
}
}
funcqueueDanmaku(msg:Msg){
danmakuQueue.addOperation(NSBlockOperation(block:{[weakself]in
ifletweakself=self{
repeat{
//检测放第几行
forvarrow=0;row<weakself.DANMAKU_MAX_ROW;++row{
letrowDanmaku=weakself.rowArray[row]
ifrowDanmaku.count==0{
letdanmaku=Danmaku(msg,weakself.danmakuFont,row)
weakself.rowArray[row].append(danmaku)
self?.performSelectorOnMainThread("sendDanmaku:",withObject:danmaku,waitUntilDone:true)
return
}else{
ifletlastDanmaku=rowDanmaku.last{
ifletstartTime=lastDanmaku.startTime{
letnow=NSDate()
letseconds=now.timeIntervalSinceDate(startTime)
letwidthDuration=Double(lastDanmaku.size.width/weakself.DANMAKU_SPEED)
vardelay=seconds-weakself.DANMAKU_SPACE_TIME-widthDuration
ifdelay>=0{
delay=0
}else{
iflastDanmaku.delay>lastDanmaku.duration{
continue
}
}
letdanmaku=Danmaku(msg,weakself.danmakuFont,row,abs(delay)+lastDanmaku.delay)
weakself.rowArray[row].append(danmaku)
self?.performSelectorOnMainThread("sendDanmaku:",withObject:danmaku,waitUntilDone:true)
return
}
}
}
}
sleep(1000)
}whileself!=nil
}
}))
}
funcsendDanmaku(danmaku:Danmaku){
lettext="\(danmaku.msg.user_name):\(danmaku.msg.text)"
letsize=NSString(string:text).sizeWithAttributes([NSFontAttributeName:danmakuFont])
letwidth=UIScreen.mainScreen().bounds.size.width
lettop=54+danmaku.row*(Int(size.height)+10)
letlabel=UILabel(frame:CGRectMake(width,CGFloat(top),size.width,size.height))
letduration=(width+size.width)/DANMAKU_SPEED
danmaku.view=label
danmaku.size=size
danmaku.startTime=NSDate()
danmaku.duration=NSTimeInterval(duration)
label.text=text
label.font=danmakuFont
label.textColor=UIColor.whiteColor()
label.shadowColor=UIColor.blackColor()
label.shadowOffset=CGSizeMake(0,-1.0)
self.view.addSubview(label)
UIView.animateWithDuration(Double(duration),delay:danmaku.delay,options:UIViewAnimationOptions.CurveLinear,animations:{()->Voidin
label.left=-label.width
}){[weakself](Bool)->Voidin
if!(self?.rowArray[danmaku.row].isEmpty??true){
self?.rowArray[danmaku.row].removeFirst()
}
label.removeFromSuperview()
}
}
代码说明:
代码控制了最多同时只能弹三行,每行最后一条如果延迟大于跑弹幕的时间(已经有一条处于完全等待状态)就自动切到下一行,超过最大限制就等待。
*rowArray主要用于查询前一个弹幕的位置和时间
*别忘了在deinit里面加上danmakuQueue.cancelAllOperations()
*注意NSBlockOperation的block并不在主线程上
以上就是对IOS开发简单的弹幕功能的实现代码,有需要开发这种功能的朋友可以参考下。