Drawing danmaku in DanmakuKit follows a three-step process involving a model, a view, and the main view controller.
1. Implement a DanmakuCellModel
Create a class that inherits from DanmakuCellModel. You must define properties for your content and override cellClass to return your custom DanmakuCell type. You should also implement calculateSize() to determine the dimensions of the danmaku.
2. Implement a DanmakuCell
Create a class that inherits from DanmakuCell. You must override the displaying(_:_:_:) method. This method provides a CGContext where you use Core Graphics to draw your content.
Important: The displaying method may be called on a background thread, so ensure your drawing logic is thread-safe.
3. Shoot the Danmaku to DanmakuView
Initialize a DanmakuView, create your model instance, configure its properties (like text, displayTime, and type), and call shoot(danmaku:) to add it to the view.
// 1. Model
class DanmakuTextCellModel: DanmakuCellModel {
var identifier = ""
var text = ""
var font = UIFont.systemFont(ofSize: 15)
var offsetTime: TimeInterval = 0
var cellClass: DanmakuCell.Type { return DanmakuTextCell.self }
var size: CGSize = .zero
var track: UInt?
var displayTime: Double = 8
var type: DanmakuCellType = .floating
var isPause = false
func calculateSize() {
size = NSString(string: text).boundingRect(with: CGSize(width: CGFloat(Float.infinity), height: 20), options: [.usesFontLeading, .usesLineFragmentOrigin], attributes: [.font: font], context: nil).size
}
func isEqual(to cellModel: DanmakuCellModel) -> Bool {
return identifier == cellModel.identifier
}
}
// 2. View
class DanmakuTextCell: DanmakuCell {
required init(frame: CGRect) { super.init(frame: frame); backgroundColor = .clear }
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
override func displaying(_ context: CGContext, _ size: CGSize, _ isCancelled: Bool) {
guard let model = model as? DanmakuTextCellModel else { return }
let text = NSString(string: model.text)
context.setLineWidth(1)
context.setLineJoin(.round)
context.setStrokeColor(UIColor.white.cgColor)
context.saveGState()
context.setTextDrawingMode(.stroke)
let attributes: [NSAttributedString.Key: Any] = [.font: model.font, .foregroundColor: UIColor.white]
text.draw(at: .zero, withAttributes: attributes)
context.restoreGState()
context.setTextDrawingMode(.fill)
text.draw(at: .zero, withAttributes: attributes)
}
}
// 3. Usage
let danmakuView = DanmakuView(frame: CGRect(x: 0, y: 0, width: 350, height: 250))
view.addSubview(danmakuView)
let cellModel = DanmakuTextCellModel(json: nil)
cellModel.displayTime = 8
cellModel.text = "Hello Danmaku"
cellModel.identifier = "unique_id"
cellModel.calculateSize()
cellModel.type = .floating
danmakuView.shoot(danmaku: cellModel)