Sprite kit 勾勒字体轮廓或去除阴影的最佳方法是什么?

Sprite kit 勾勒字体轮廓或去除阴影的最佳方法是什么?,sprite-kit,Sprite Kit,我在Sprite工具包中找不到对dropshadow或字体轮廓的任何支持。对于dropshadow,我猜我可以创建第二个SKLabelNode并将其偏移到另一个之后 是否有某种方法可以利用SKEffectNode作为轮廓或dropshadow?是否可能使SKLabelNode成为SKEffectNode的子节点 更新: 我能够使用第一个节点后面的第二个SKLabelNode获得一个像样的dropshadow,即黑色和偏移。仍然对其他可能的选项感兴趣,但这似乎很有效。关于概述: 简短的回答:你的工

我在Sprite工具包中找不到对dropshadow或字体轮廓的任何支持。对于dropshadow,我猜我可以创建第二个SKLabelNode并将其偏移到另一个之后

是否有某种方法可以利用SKEffectNode作为轮廓或dropshadow?是否可能使SKLabelNode成为SKEffectNode的子节点

更新:


我能够使用第一个节点后面的第二个SKLabelNode获得一个像样的dropshadow,即黑色和偏移。仍然对其他可能的选项感兴趣,但这似乎很有效。

关于概述:

简短的回答:你的工作很适合你。
长回答:你的工作真的很适合你

我们已经在一个项目中这样做了,基本的方法是创建一个UILabel,并将其渲染成一个进入精灵的纹理。
要将轮廓添加到UILabel上,可以使用以下方法: 要将其渲染为UIImage(您可以使用[SKTexture textureWithImage:img]生成纹理),请使用以下命令: 这带来了一大堆问题,其中最主要的是缓慢、贪婪的渲染,这在很大程度上是通过尽可能为静态文本预渲染到文件来解决的


我不认为你能通过一个效果节点来实现这一点,因为字体往往需要精确性。回想起来,在走这条路之前,我会三思而后行。

这很可能是您正在做的事情,但它很有效而且很简单

- (SKLabelNode *) makeDropShadowString:(NSString *) myString
{
    int offSetX = 3;
    int offSetY = 3;

    SKLabelNode *completedString = [SKLabelNode labelNodeWithFontNamed:@"Arial"];
    completedString.fontSize = 30.0f;
    completedString.fontColor = [SKColor yellowColor];
    completedString.text = myString;


    SKLabelNode *dropShadow = [SKLabelNode labelNodeWithFontNamed:@"Arial"];
    dropShadow.fontSize = 30.0f;
    dropShadow.fontColor = [SKColor blackColor];
    dropShadow.text = myString;
    dropShadow.zPosition = completedString.zPosition - 1;
    dropShadow.position = CGPointMake(dropShadow.position.x - offSetX, dropShadow.position.y - offSetY);

    [completedString addChild:dropShadow];

    return completedString;
}
我也会试着做一个提纲。。。但我有一种感觉那会更棘手。。。必须有一种使用位图字体的方法???bmGlyph…

这对我很有用:

以下是我与ASAttributedLabelNode一起使用的代码(其中一些代码对我来说是特定的,比如字体名/size/fillcolor/outlinecolor,但当然只使用您自己的代码):

使用此功能时,请同时执行以下操作:

    let hintSize = CGFloat(80.0)
    let hintLabel = ASAttributedLabelNode(size:CGSizeMake(playableRect.size.width*0.9, hintSize))

    hintLabel.attributedString = outlinedCenteredString("Touch the Rope to Release the Wood", size: hintSize)

    hintLabel.position =
        CGPointMake(
            size.width/2.0,
            ((size.height - playableRect.size.height)/2.0) + hintSize/2.0
    )

    hintLabel.zPosition = kHintZPosition
    addChild(hintLabel)

我不仅使用了这里描述的“2SklabelNode”dropshadow技术,而且还添加了三个“DropShadows”,从而获得了某种程度上可以接受的“轮廓”

换言之,一旦底部阴影就位,再添加三个。一个向顶部偏移,一个向右侧偏移,一个向左侧偏移-因此我在下面有四个“放置阴影”,主标签位于顶部,总共有五个SKLabelNodes,仅用于创建此轮廓效果

在我的应用程序中,我必须设置这个文本的动画,所以我更进一步,用这五个标签创建了一个位图纹理,并用这个纹理创建了一个SKSpriteNode,这样我就可以删除五个原始标签节点,并设置位图版本的动画

还值得注意的是,通过从标签节点创建纹理,它会导致模糊纹理,我通过在创建纹理之前将标签节点的大小加倍,然后将生成的纹理的大小减小50%来修复模糊纹理

我附上一张图片,向您展示结果。这可能不是最优雅的方法,但它似乎适合我的特殊情况。希望这有帮助

使用OOP! 我已经将其实现为一个新组件,一个SKNode的后代 包含两个SKLabelNodes,一个用于文本本身,另一个用于其阴影:

final class TgSKLabelWithShadow: SKNode
{
    private var lblText: SKLabelNode!
    private var lblShadow: SKLabelNode!

    var text: String?
        {     get { return lblText.text }
        set { lblText.text   = newValue
              lblShadow.text = newValue   } }

    var fontColor: UIColor?
        { get { return lblText.fontColor     }
          set { lblText.fontColor = newValue } }
    // define additional getters/setters, if necessary.


    init(     position: CGPoint,
              alignment: SKLabelHorizontalAlignmentMode,
              text: String,
              fontName: String,
              fontSize: CGFloat,
              fontColor: UIColor,
              shadowColor: UIColor,
              shadowOffSet: CGPoint)
    {
        super.init()
        self.position = position

        lblShadow = SKLabelNode(text: text)
        lblShadow.fontName  = fontName
        lblShadow.fontColor = shadowColor
        lblShadow.fontSize  = fontSize
        lblShadow.horizontalAlignmentMode = alignment
        lblShadow.position = shadowOffSet
        self.addChild(lblShadow)  // add shadow first

        lblText = SKLabelNode(text: text)
        lblText.fontName  = fontName
        lblText.fontColor = fontColor
        lblText.fontSize  = fontSize
        lblText.horizontalAlignmentMode = alignment
        self.addChild(lblText)  // on top of shadow
    }

    required init?(coder aDecoder: NSCoder)
    {
        fatalError("TgSKLabelWithShadow - init(coder:) has not been implemented")
    }
}
实例化并添加到父节点(另一个节点或场景),如下所示:

   ndInfo2 = TgSKLabelWithShadow(
        position: CGPoint(x: size.width/2, y:   size.height - 170),
        alignment : .Center,
        text: "ndInfo2: ???",
        fontName: "Avenir",
        fontSize: 40,
        fontColor: colorText,
        shadowColor: UIColor.blueColor(),
        shadowOffSet: CGPoint(x:1, y:-1))
    addChild(ndInfo2)
大纲?好吧,没有什么能阻止你嵌套另一个SKLabelNode来建立一个轮廓。(可以计算出它比标签稍大。)注意,添加子标签的顺序是相关的

这段代码已经过测试,目前正在我正在构建的苹果电视应用程序中积极使用。谢谢你,特德。我建议你

例如:

let textNode = MKOutlinedLabelNode(fontNamed: "Helvetica", fontSize: 32)
textNode.borderColor = UIColor.blackColor()
textNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Center
textNode.fontColor = UIColor.blueColor()
textNode.outlinedText = "Test"


您也可以签出。

我创建了一个继承自SKSpriteNode的类,它根据传递给构造函数的参数创建必要的SKLabelNode和4个阴影标签

更改任何公共属性时,都需要调用update()方法。(大于6-7的边框看起来很有趣。)


最近的代码可以在

中找到,因为iOS 11 SKLabelNode已经发布。您需要指定
strokeColor
strokeWidth
,并且不要忘记
font
foregroundColor
,进一步说明Kelin的优点,下面是它的Swift 4代码:

var label: SKLabelNode!
let attStr: NSMutableAttributedString = NSMutableAttributedString(string: "MyDefaultText")
let myFont: UIFont = UIFont(name: "FontName", size: 7)!

attStr.mutableString.setString("MyText")
attStr.addAttribute(.font, value: myFont, range: NSMakeRange(0, attStr.length))
attStr.addAttribute(.foregroundColor, value: UIColor.white, range: NSMakeRange(0, attStr.length))
attStr.addAttribute(.strokeColor, value: UIColor.red, range: NSMakeRange(0, attStr.length))
attStr.addAttribute(.strokeWidth, value: -3.0, range: NSMakeRange(0, attStr.length))

label.attributedText = attStr

PS:要同时获得笔划和填充,需要对
.strokeWidth
应用负值,这意味着笔划向外。
.strokeWidth
的正值将向内发送笔划,并导致填充颜色(
.foregroundColor
)消失

Erica Sadun曾基于
SKEffectNode

我最近不得不创建她的Swift4版本
ShadowLabelNode

我现在可以用两个SklabelNode得到一个不错的dropshadow,其中一个是offset和黑色。对于SKEffectNode,您可以使用shouldRasterize选项来缓存它。我将对答案进行编辑以尽可能多地反映。为什么不像你说的那样用两个SKLabel来制作阴影呢?是的,就像我说的,我已经试过了,它对阴影效果很好。我在寻找我可能没有想到或不知道的提纲和阴影投影选项。我不清楚你的答案如何提供提纲选项。转换成图像并不能给我一个轮廓。还是我在这里遗漏了什么?UILabel是否支持dropshadow/outline?好的,我会研究一下。我将把这个问题留一段时间,希望有其他选择。我使用SpriteKit管理了一个令人满意的dropshadow,如果可能的话,我希望避免使用UILabel解决方案。我确实找到了dropshadow,就像您在这里看到的一样。这个提纲我还没想好怎么做。我想我
import Foundation
import SpriteKit

class LFOutlinedLabel : SKSpriteNode {

    private let skewX : [CGFloat] = [-1, 1, 1,-1]
    private let skewY : [CGFloat] = [-1,-1, 1, 1]

    private var label : SKLabelNode = SKLabelNode()
    private var shadows : [SKLabelNode] = []

    public var borderOpacity : CGFloat = 1
    public var borderSize: CGFloat = 1
    public var borderColor: UIColor = UIColor.black
    public var text : String = "?"
    public var fontName : String = Fonts.OptimaExtraBlack.rawValue
    public var fontColor: UIColor = UIColor.white
    public var fontSize : CGFloat = 40

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        //self.setup()
    }

    override init(texture: SKTexture!, color: UIColor, size: CGSize) {
        super.init(texture: texture, color: color, size: size)
        //self.setup()
    }

    convenience init(size: CGSize, font: String, fSize: CGFloat, fColor: UIColor, bSize: CGFloat, bColor: UIColor, bOpacity: CGFloat)
    {
        self.init(texture: nil, color: UIColor.clear, size: size)
        self.fontName = font
        self.fontSize = fSize
        self.fontColor = fColor
        self.borderSize = bSize
        self.borderColor = bColor
        self.borderOpacity = bOpacity
        self.setup()
    }

    // create shadow labels
    private func setup() {
        if shadows.count == 0 {
            let width = self.size.width / 2
            let height = self.size.height / 2
            for j in 0...3 {
                let shadow = SKLabelNode(text: self.text)
                addChild(shadow)
                shadow.verticalAlignmentMode = .center
                shadow.horizontalAlignmentMode = .center
                shadow.zPosition = 999
                shadow.position = CGPoint(x: width + (skewX[j] * borderSize) , y: height + (skewY[j] * borderSize))
                shadow.text = self.text
                shadow.fontSize = self.fontSize
                shadow.fontName = self.fontName
                shadow.fontColor = borderColor
                shadows.append(shadow)
            }
            let label = SKLabelNode(text: self.text)
            addChild(label)
            label.verticalAlignmentMode = .center
            label.horizontalAlignmentMode = .center
            label.zPosition = 1000
            label.position = CGPoint(x: width , y: height )
            label.text = self.text
            label.fontSize = self.fontSize
            label.fontName = self.fontName
            label.fontColor = fontColor
            self.label = label
        }
    }

    public func update(){
        let width = self.size.width / 2
        let height = self.size.height / 2

        self.label.fontSize = fontSize
        self.label.fontName = fontName
        self.label.fontColor = fontColor
        self.label.verticalAlignmentMode = .center
        self.label.horizontalAlignmentMode = .center
        self.label.text = text
        self.label.position = CGPoint(x: width  , y: height )

        for i in 0...3 {
            shadows[i].verticalAlignmentMode = .center
            shadows[i].horizontalAlignmentMode = .center
            shadows[i].fontColor = borderColor
            shadows[i].fontSize = fontSize
            shadows[i].alpha = borderOpacity
            shadows[i].fontName = fontName
            shadows[i].text = text
            shadows[i].position = CGPoint(x: width + (skewX[i] * borderSize) , y: height + (skewY[i] * borderSize) )
        }
    }
}
var label: SKLabelNode!
let attStr: NSMutableAttributedString = NSMutableAttributedString(string: "MyDefaultText")
let myFont: UIFont = UIFont(name: "FontName", size: 7)!

attStr.mutableString.setString("MyText")
attStr.addAttribute(.font, value: myFont, range: NSMakeRange(0, attStr.length))
attStr.addAttribute(.foregroundColor, value: UIColor.white, range: NSMakeRange(0, attStr.length))
attStr.addAttribute(.strokeColor, value: UIColor.red, range: NSMakeRange(0, attStr.length))
attStr.addAttribute(.strokeWidth, value: -3.0, range: NSMakeRange(0, attStr.length))

label.attributedText = attStr