DanmuManager 一個簡單的彈幕工具
DanmuManager 和 VideoDanmuManager 有不同的應用場景,后者用于視頻彈幕。
你可以運行項目中的測試,來了解二者的使用方法。
DanmuManager
-
創建 DanmuManager
let dm = DanmuManager(with: self.view)
init` 方法允許自定義:
- `top`、`bottom`彈幕顯示在 `view` 中的上下位置范圍;
- `speed` 彈幕的速度;
- `customFont` 彈幕字體(`UIFont`, 包括字體家族和大小,默認為系統字體,字號 20)。
-
添加一條彈幕
dm.add(with: “Wow so cool!!!”, at: 4)
add` 方法有兩個必傳參數,`text`(彈幕文字) 和 `line`(彈幕所在行);可選參數 `hasBorder` 用于設置該條彈幕是否有邊框(默認 borderColor = UIColor.black.cgColor,borderWidth = 1),默認值為 false;可選參數 `isAdvance` 用于設置該條彈幕是否開啟高級功能(目前支持修改 文字顏色 和 背景顏色),默認值為 false。
如果需要彈幕出現在隨機行,可以使用
`func addRandom(with text: String = "This is a test Danmu.", at line: Int = 0, hasBorder: Bool = false, isAdvanced: Bool = false)`。
-
暫停/繼續 彈幕
dm.pause() dm.resume()
你也可以使用 `dm.toggle()` 來快捷切換 暫停/繼續。
VideoDanmuManager
-
創建 VideoDanmuManager
let vdm = VideoDanmuManager(view: self.view, videoLength: 10, danmuData: [ (3.4, "3.4 Wowowowowowow!"), (3.4, "3.4 SOOOO COOOOOOOOOOL!"), (3.4, "3.4 Amazing!!!!"), (3.4, "3.4 I love you~"), (3.4, "3.4 MY BABY!!!!"), (1.1, "1.1 This is a test Danmu!!!"), (2.0, "2.0 Another test Danmu."), (4.1, "4.1 Amazing!!!!"), (6.1, "6.1 Test!!!!"), (8.1, "8.1 Test!!!!"), (9.1, "9.1 Test!!!!"), (10, "10 Test!!!!"), ], isSorted: false )
VideoDanmuManager` 的創建有三個必選參數,`view`(顯示彈幕的視圖),`videoLength`(視頻時長,精確到 0.1 秒)和 `danmuData`(已經存在的彈幕列表)。
可選參數 `videoCurrent` 默認為 0,即開始時刻;你可以通過傳入不同的時間值來設置顯示彈幕的初始時間(比如在視頻從 1 分 15 秒開始播放,則應設置 `videoCurrent` 為 75)。
可選參數 `isSorted` 默認為 true,即默認數據集已經按照彈幕顯示時間從先到后排序;如傳入 false,則將自動調用 `func sort()` 對數據進行排序。
可選參數 `top` 和 `bottom` 同 `DanmuManager`。
-
開啟彈幕
vdm.start()
你需要在視頻開始播放的同時,手動開啟彈幕。
-
暫停/繼續 彈幕
vdm.pause() vdm.resume()
你也可以使用 `vdm.toggle()` 來快捷切換 暫停/繼續。
-
中止彈幕
vdm.stop()
-
重新開始彈幕
vdm.restart()
你也可以在指定時間點重新開始彈幕:
vdm.restart(at: 75)
設計思路
DanmuManager 通過設置的字體大小計算文本顯示高度 lineHeight ,通過 numberOfLines = Int(floor((bottom - top) / lineHeight)) 得到可以顯示的彈幕行數;使用 inUsingLines , enteringTimers 和 waitingQueues 來分別記錄 正在使用的行(有尾部還沒有完全進入視圖的彈幕的行),正在進入視圖的彈幕的計時器 和 正在等待進入的彈幕隊列。
為了防止彈幕重疊,只有當 當前行中前一條彈幕尾部進入視圖 時(之后),下一條彈幕才可以發射。
enteringTimers 中每一個 Timer 都對應一條正在進入視圖的彈幕,當計時器結束時,通過 NotificationCenter 發通知將該彈幕所在的行的狀態更改為 false。
因為彈幕存在暫停狀態,如果彈幕對應的 Timer 不同時暫停,將導致 彈幕所在行狀態 提前更改為 false。為了解決這個問題,我參考他人的想法并改進后創建了 PauseableTimer,并在本項目中使用上了。我的另外一篇博客更詳細地介紹了 PauseableTimer 。
為了避免手動發射彈幕和自動發射隊列中的彈幕出現沖突(彈幕重疊),所有彈幕通過 taskTimer 定時任務統一調度。
下一步 Next Step
現在流行的彈幕功能越來越復雜、高級,DanmuManager 只是完成了最基礎的滾動文字彈幕功能。未來可能會學習常見的彈幕,添加一些更高級的功能,比如 對滾動彈幕的操作,居中彈幕 等。
來自:http://chengkang.me/2017/01/05/DanmuManager 一個簡單的彈幕工具/