【Swift 2.0】实现简单弹幕功能

简介:

前言

  简单实现弹幕功能,表跟我谈效率,但也有用队列控制同时弹的数量。

 

声明 
欢迎转载,但请保留文章原始出处:) 
博客园:http://www.cnblogs.com
农民伯伯: http://over140.cnblogs.com

 

正文

复制代码
    let DANMAKU_SPEED: CGFloat = 150    // 弹幕每秒移动速度
    let DANMAKU_SPACE_TIME: NSTimeInterval = 1    // 弹幕之间的时间间隔
    let DANMAKU_MAX_ROW = 3    // 最多同时弹幕行数
    let danmakuFont = UIFont.systemFontOfSize(18)    // 弹幕字体大小
    var rowArray = Array<Array<Danmaku>>(count: 3, repeatedValue: Array<Danmaku>())    
    var danmakuQueue = NSOperationQueue()    // 队列

    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 {
                    //检测放第几行
                    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()
        }
    }
复制代码

    代码说明:

      代码控制了最多同时只能弹三行,每行最后一条如果延迟大于跑弹幕的时间(已经有一条处于完全等待状态)就自动切到下一行,超过最大限制就等待。

      *  rowArray 主要用于查询前一个弹幕的位置和时间

      *  别忘了在 deinit 里面加上 danmakuQueue.cancelAllOperations()

      *  注意 NSBlockOperation 的 block 并不在主线程上


转载:http://www.cnblogs.com/over140/p/4861347.html

目录
相关文章
在Swift中实现撤销功能
本文讲的是在Swift中实现撤销功能,在过去的一段时间里,有很多的Blog推出了关于他们想在Swift中所添加的动态特性的文章。事实上Swift 已经成为了一门具有相当多动态特性的语言:它拥有泛型,协议, 头等函数(译者注1:first-class function指函数可以向类一样作为参数传递)
1167 0
|
缓存 索引
Swift 绘图板功能完善以及终极优化
转载请注明出处:http://blog.csdn.net/zhangao0086/article/details/45289475。
1201 0
|
算法 iOS开发
Swift 全功能的绘图板开发
转载请注明出处:http://blog.csdn.net/zhangao0086/article/details/43836789。
1276 0
|
Swift 网络架构
swift UI专项训练40 用swift实现打电话和发短信功能
   今天来讲一下如何让我们的APP可以访问系统的短信和电话功能。首先来说短信功能,比较简单,跟之前的做法差别不大,要使用UIApplication,它是一个单例。
968 0
swift UI专项训练39 用Swift实现摇一摇功能
   微信的摇一摇功能想必大家都用过,过年的时候抢红包也没少摇吧,那么用swift语言如何实现这么酷炫的功能呢。
972 0
|
4月前
|
Unix 调度 Swift
苹果iOS新手开发之Swift 中获取时间戳有哪些方式?
在Swift中获取时间戳有四种常见方式:1) 使用`Date`对象获取秒级或毫秒级时间戳;2) 通过`CFAbsoluteTimeGetCurrent`获取Core Foundation的秒数,需转换为Unix时间戳;3) 使用`DispatchTime.now()`获取纳秒级精度的调度时间点;4) `ProcessInfo`提供设备启动后的秒数,不表示绝对时间。不同方法适用于不同的精度和场景需求。
131 3
|
10天前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户点击按钮时,按钮将从圆形变为椭圆形,颜色从蓝色渐变到绿色;释放按钮时,动画以相反方式恢复。通过UIView的动画方法和弹簧动画效果,实现平滑自然的过渡。
24 1