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开发简单的弹幕功能的实现代码,有需要开发这种功能的朋友可以参考下。