swift 2 sprite-kit 中的多行标签?
Posted
技术标签:
【中文标题】swift 2 sprite-kit 中的多行标签?【英文标题】:Multi-line label in swift 2 sprite-kit? 【发布时间】:2016-02-01 00:51:06 【问题描述】:我需要能够在 swift 2 sprite-kit 中为游戏制作多行标签。文本需要环绕而不是离开屏幕。贝娄是我所拥有的,但我不知道该怎么做
import Foundation
import UIKit
import SpriteKit
class JDQuotes: SKLabelNode
var number = 0
init(num: Int)
super.init()
if num == 1
text = "\"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. laborum.\""
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
【问题讨论】:
我只需要一个 UIlabel 并作为子视图添加到 SKView 之上。 这里是第三方解决方案。 SKLabel 通常不支持多行。https://craiggrummitt.wordpress.com/2015/04/10/multi-line-sklabels-in-swift/
【参考方案1】:
从 ios 11 开始,这终于可以通过 SKLabelNode
实现了:
let lb = SKLabelNode(fontNamed: "Copperplate")
lb.text = "Put your long text here..."
lb.numberOfLines = 0
lb.preferredMaxLayoutWidth = 1000
【讨论】:
请注意,numberOfLines
和 preferredMaxLayoutWidth
等较新的方法仅适用于 iOS 11.0 或更高版本。所以如果你想支持旧版本,你将不得不放弃这些方法。【参考方案2】:
here 上有一个 Github 解决方案,因为 SKLabelNodes 不支持多行。
引用代码:
import SpriteKit
class SKMultilineLabel: SKNode
//props
var labelWidth:Int didSet update()
var labelHeight:Int = 0
var text:String didSet update()
var fontName:String didSet update()
var fontSize:CGFloat didSet update()
var pos:CGPoint didSet update()
var fontColor:UIColor didSet update()
var leading:Int didSet update()
var alignment:SKLabelHorizontalAlignmentMode didSet update()
var dontUpdate = false
var shouldShowBorder:Bool = false didSet update()
//display objects
var rect:SKShapeNode?
var labels:[SKLabelNode] = []
init(text:String, labelWidth:Int, pos:CGPoint, fontName:String="ChalkboardSE-Regular",fontSize:CGFloat=10,fontColor:UIColor=UIColor.blackColor(),leading:Int=10, alignment:SKLabelHorizontalAlignmentMode = .Center, shouldShowBorder:Bool = false)
self.text = text
self.labelWidth = labelWidth
self.pos = pos
self.fontName = fontName
self.fontSize = fontSize
self.fontColor = fontColor
self.leading = leading
self.shouldShowBorder = shouldShowBorder
self.alignment = alignment
super.init()
self.update()
//if you want to change properties without updating the text field,
// set dontUpdate to false and call the update method manually.
func update()
if (dontUpdate) return
if (labels.count>0)
for label in labels
label.removeFromParent()
labels = []
let separators = NSCharacterSet.whitespaceAndNewlineCharacterSet()
let words = text.componentsSeparatedByCharactersInSet(separators)
let len = countElements(text)
var finalLine = false
var wordCount = -1
var lineCount = 0
while (!finalLine)
lineCount++
var lineLength = CGFloat(0)
var lineString = ""
var lineStringBeforeAddingWord = ""
// creation of the SKLabelNode itself
var label = SKLabelNode(fontNamed: fontName)
// name each label node so you can animate it if u wish
label.name = "line\(lineCount)"
label.horizontalAlignmentMode = alignment
label.fontSize = fontSize
label.fontColor = UIColor.whiteColor()
while lineLength < CGFloat(labelWidth)
wordCount++
if wordCount > words.count-1
//label.text = "\(lineString) \(words[wordCount])"
finalLine = true
break
else
lineStringBeforeAddingWord = lineString
lineString = "\(lineString) \(words[wordCount])"
label.text = lineString
lineLength = label.width
if lineLength > 0
wordCount--
if (!finalLine)
lineString = lineStringBeforeAddingWord
label.text = lineString
var linePos = pos
if (alignment == .Left)
linePos.x -= CGFloat(labelWidth / 2)
else if (alignment == .Right)
linePos.x += CGFloat(labelWidth / 2)
linePos.y += CGFloat(-leading * lineCount)
label.position = CGPointMake( linePos.x , linePos.y )
self.addChild(label)
labels.append(label)
//println("was \(lineLength), now \(label.width)")
labelHeight = lineCount * leading
showBorder()
func showBorder()
if (!shouldShowBorder) return
if let rect = self.rect
self.removeChildrenInArray([rect])
self.rect = SKShapeNode(rectOfSize: CGSize(width: labelWidth, height: labelHeight))
if let rect = self.rect
rect.strokeColor = UIColor.whiteColor()
rect.lineWidth = 1
rect.position = CGPoint(x: pos.x, y: pos.y - (CGFloat(labelHeight) / 2.0))
self.addChild(rect)
编辑: 您也可以查看this version,因为它已针对 Swift2 进行了更新
【讨论】:
这样做的一个问题是 SKLabelNode 不像 SKSpriteNode 那样批量渲染。因此,如果您有 20 行标签,则需要 20 次绘制通道,这可能会影响性能。您可以尝试向 SKEffectNode 添加多标签实例,然后对其进行栅格化。这会将多行标签渲染所需的绘制通道减少到 1。 到目前为止,我还没有注意到它存在极端的性能问题。不过,我并没有过度使用多行标签,所以你可能是对的。 感谢您的努力,不要误会我的意思,但您无法处理某些情况。传递比labelWidth
更长的字符串将进入无限循环(在说话的那一刻)。
我在 Gist 上的解决方案(在上面的答案中引用)现在已针对 Swift 3 进行了更新。gist.github.com/craiggrummitt/03bfa93c07e247ee9358以上是关于swift 2 sprite-kit 中的多行标签?的主要内容,如果未能解决你的问题,请参考以下文章