概述或隐藏字体的最佳方法是什么?

时间:2013-10-06 17:40:54

标签: sprite-kit

我没有在Sprite Kit中找到任何支持Drophadow或字体轮廓的内容。对于Drophadow,我猜我可以创建第二个SKLabelNode并将其偏移到另一个之后。

是否有某种方法可以将SKEffectNode用于轮廓或阴影?可能使SKLabelNode成为SKEffectNode的子项?

更新:

我能够使用第一个后​​面的第二个SKLabelNode得到一个体面的阴影,即黑色和偏移。仍然对其他潜在的选择感兴趣,但这似乎运作良好。

10 个答案:

答案 0 :(得分:17)

这很可能是你正在做的,但它很有效,而且很简单。

- (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 ......

答案 1 :(得分:5)

由于iOS 11 SKLabelNode有attributedText property。您需要指定strokeColorstrokeWidth并且不要忘记fontforegroundColor

答案 2 :(得分:4)

我已经能够达到一个可以接受的"大纲"通过不仅使用" 2 SKLabelNode"这里描述的阴影技术,还可以添加三个"阴影"。

换句话说,一旦你有底部阴影,再添加三个。一个偏向顶部,一个向右偏移,一个向左偏移 - 所以我有四个"阴影"在下面,主要标签位于顶部,共有五个SKLabelNodes,用于创建此轮廓效果。

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

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

我附上图片以显示结果。它可能不是最优雅的方法,但它似乎适用于我的特殊情况。希望这有帮助!

enter image description here

答案 3 :(得分:2)

我建议MKOutlinedLabelNode

示例:

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

enter image description here

您还可以查看ASAttributedLabelNode

答案 4 :(得分:1)

这对我有用:

http://battleofbrothers.com/sirryan/outline-text-in-spritekit

这是我与ASAttributedLabelNode一起使用的代码(其中一些特定于我的字体名称/尺寸/ fillcolor / outlinecolor,但当然只使用您自己的代码):

func outlinedCenteredString(string : String, size: CGFloat) -> NSAttributedString
{
    var myMutableString : NSMutableAttributedString
    var font =  UIFont(name: "Super Mario 256", size: size)!
    var alignment : CTTextAlignment = CTTextAlignment.TextAlignmentCenter
    let alignmentSetting = [CTParagraphStyleSetting(spec: .Alignment, valueSize: Int(sizeofValue(alignment)), value: &alignment)]
    var paragraphRef = CTParagraphStyleCreate(alignmentSetting, 1)

    let textFontAttributes = [
        NSFontAttributeName : font,
        // Note: SKColor.whiteColor().CGColor breaks this
        NSForegroundColorAttributeName: UIColor.yellowColor(),
        NSStrokeColorAttributeName: UIColor.blackColor(),
        // Note: Use negative value here if you want foreground color to show
        NSStrokeWidthAttributeName:-3
        //,NSParagraphStyleAttributeName: paragraphRef
    ]

    myMutableString = NSMutableAttributedString(string: string, attributes: textFontAttributes as [NSObject : AnyObject])

    let para = NSMutableParagraphStyle()
    para.headIndent = 00
    para.firstLineHeadIndent = 00
    para.tailIndent = 0
    para.lineBreakMode = .ByWordWrapping
    para.alignment = .Center
    para.paragraphSpacing = 0
    myMutableString.addAttribute(
        NSParagraphStyleAttributeName,
        value:para, range:NSMakeRange(0,1))
    return myMutableString
}

以及以下内容使用此功能:

    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)

答案 5 :(得分:1)

除了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:要同时获取笔划填充,您需要将否定值应用于{{1这意味着笔划向外。 .strokeWidth的正值会向内发送笔触并导致填充色(.strokeWidth)消失!

答案 6 :(得分:0)

关于概述:

简短的回答:你已经为你裁掉了工作 答案很长:你真的为你做了工作。

我们一直在项目中这样做,基本方法是创建一个UILabel并将其渲染为一个进入精灵的纹理。
要将轮廓绘制到UILabel上,您可以使用: How do I make UILabel display outlined text? 并将其呈现为UIImage(您可以使用[SKTexture textureWithImage:img]创建纹​​理),使用此: How to create an image from UILabel? 这带来了一大堆问题,其中最主要的是缓慢,贪婪的渲染,这在很大程度上通过预渲染到静态文本的文件来解决。

我认为你不能用效果节点来解决这个问题,因为字体往往需要精确度。回想起来,在走这条路之前我会三思而后行。

答案 7 :(得分:0)

使用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来建立一个轮廓。 (可以将其计算为略大于标签。)请注意,添加子标签的顺序是相关的。

此代码已经过测试,并且正在我正在制作的Apple TV应用中正在使用。亲切的问候,特德。

答案 8 :(得分:0)

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

更改任何公共属性时,需要调用update()方法。 (BorderSize超过6-7看起来很有趣。)

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) )
        }
    }
}

最近的代码可以在https://gist.github.com/detaybey/214b23731a3b4d0344ce58643795f4b7

找到

答案 9 :(得分:0)

Erica Sadun曾经基于SKEffectNode here

创建了一个投影

我最近不得不为她的ShadowLabelNode创建一个Swift4版本: https://gist.github.com/Bersaelor/d6ea241278665173485e8aabafbe9047