IOS implements a simple barrage function
- 2020-05-17 06:37:36
- OfStack
preface
Simply implement the bullet screen function, table to talk to me about efficiency, but also useful for queue control of the number of simultaneous bullets.
The body of the
Code implementation:
let DANMAKU_SPEED: CGFloat = 150 // The barrage moves every second
let DANMAKU_SPACE_TIME: NSTimeInterval = 1 // The time interval between the barrage
let DANMAKU_MAX_ROW = 3 // Maximum number of simultaneous barrage lines
let danmakuFont = UIFont.systemFontOfSize(18) // Bullet screen font size
var rowArray = Array<Array<Danmaku>>(count: 3, repeatedValue: Array<Danmaku>())
var danmakuQueue = NSOperationQueue() // The queue
class Danmaku : NSObject{
var msg: Msg
var view: UILabel?
var size = CGSize(width: 0, height: 0)
var row = 0
var startTime: NSDate?
var duration: NSTimeInterval = 0
var delay: NSTimeInterval = 0
init(_ msg: Msg, _ row: Int, _ delay: NSTimeInterval = 0) {
self.msg = msg
self.row = row
self.delay = delay
}
}
func queueDanmaku(msg: Msg) {
danmakuQueue.addOperation(NSBlockOperation(block: { [weak self] in
if let weakself = self {
repeat {
// Check which line to put
for var row = 0; row < weakself.DANMAKU_MAX_ROW; ++row {
let rowDanmaku = weakself.rowArray[row]
if rowDanmaku.count == 0 {
let danmaku = Danmaku(msg, weakself.danmakuFont, row)
weakself.rowArray[row].append(danmaku)
self?.performSelectorOnMainThread("sendDanmaku:", withObject: danmaku, waitUntilDone: true)
return
} else {
if let lastDanmaku = rowDanmaku.last {
if let startTime = lastDanmaku.startTime {
let now = NSDate()
let seconds = now.timeIntervalSinceDate(startTime)
let widthDuration = Double(lastDanmaku.size.width / weakself.DANMAKU_SPEED)
var delay = seconds - weakself.DANMAKU_SPACE_TIME - widthDuration
if delay >= 0 {
delay = 0
} else {
if lastDanmaku.delay > lastDanmaku.duration {
continue
}
}
let danmaku = Danmaku(msg, weakself.danmakuFont, row, abs(delay) + lastDanmaku.delay)
weakself.rowArray[row].append(danmaku)
self?.performSelectorOnMainThread("sendDanmaku:", withObject: danmaku, waitUntilDone: true)
return
}
}
}
}
sleep(1000)
} while self != nil
}
}))
}
func sendDanmaku(danmaku: Danmaku) {
let text = "\(danmaku.msg.user_name) : \(danmaku.msg.text)"
let size = NSString(string: text).sizeWithAttributes([NSFontAttributeName : danmakuFont])
let width = UIScreen.mainScreen().bounds.size.width
let top = 54 + danmaku.row * (Int(size.height) + 10)
let label = UILabel(frame: CGRectMake(width, CGFloat(top), size.width, size.height))
let duration = (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: { () -> Void in
label.left = -label.width
}) { [weak self] (Bool) -> Void in
if !(self?.rowArray[danmaku.row].isEmpty ?? true) {
self?.rowArray[danmaku.row].removeFirst()
}
label.removeFromSuperview()
}
}
Code description:
The code controls that only 3 lines can be played at the same time at most. If the delay at the end of each line is greater than the running time of the barrage (there is already 1 line in the fully waiting state), it will automatically cut to the next 1 line and wait if the maximum limit is exceeded.
*rowArray is mainly used to query the location and time of the first barrage
* don't forget to add danmakuQueue.cancelAllOperations () to deinit
* note that NSBlockOperation's block is not on the main thread
The above is the IOS development of a simple bullet screen function implementation code, there is a need to develop the function of friends can refer to the next.