为什么iOS等宽字体表现不同?

4
我正在使用SpriteKit,iOS应用程序中通过SKLabelNode渲染的计时器在更新函数中被更新。由于我不希望随着计数增加数字左右移动,因此我尝试使用Courier New字体。它比Avenir表现更好,但仍然存在一些数字宽度的微小波动。(6和9略宽于其他数字。)我在几个不同的实验中看到了这些波动,其中包括:

  • 正常和粗体样式
  • 大(65)和小(9)字号
  • Courier New和Menlo字体
  • Xcode模拟器和iPod Touch

我提交了查询“哪种字体具有统一宽度的数字”,但我能找到的所有答案都只是说“使用等宽字体”。(参见https://graphicdesign.stackexchange.com/questions/13148/which-fonts-have-the-same-width-for-every-characterMonospace Font - Not really Monospace?)

我的代码非常简单。我像这样设置了scoreNode:

    scoreNode = SKLabelNode(fontNamed: "Courier New")
    scoreNode.fontSize = 65
    scoreNode.fontColor = UIColor.blackColor()
    scoreNode.text = "0"
    scoreNode.position = CGPoint(x: patternPane.midX, y: patternPane.midY)
    patternPaneNode.addChild(scoreNode)

然后我像这样更新分数:
    scoreNode.text = "\(viewControllerDelegate!.getScore())"

这是一张图片,覆盖在帧上面,展示了28和部分29的帧。你可以看到电影的边缘已经对齐了,但数字2的底部并没有对齐。

partial 29 overlaid on 28

有什么解释吗?

可能iOS正在应用字距调整(kerning)到SKLabelNode,即使我使用的是等宽字体,这是否可能呢?


1
你能否添加一张截图? - Sulthan
这是一个SKLabelNode(显示两位数)还是两个节点分别显示一位数字?如果是后者,它们之间的位置如何定义? - Martin R
它是一个带有两个数字的节点。 - mike663
我遇到了同样的问题,你找到解决方法了吗? - erhosen
2个回答

0
我遇到了同样的问题,花费了多天的时间来解决它。这是我的解决方案:
首先,设置分数的函数使用了attributedText而不是text。这使得可以使用UIFont.monospacedSystemFont()。
let labelFontSize = 17

func setScore(_ newScore: Int) {
    labelNode.attributedText = .init(
        string: String(newScore),
        attributes: [
            .font: UIFont.monospacedSystemFont(
                ofSize: labelFontSize,
                weight: .bold
            ),
            .foregroundColor: UIColor.white,
        ]
    )
}

下一步 - 修复SKLabelNodeSKShapeNode(或任何其他矩形)内的位置:
func adjustLabelToFitRect(labelNode: SKLabelNode, rect: CGRect) {
    labelNode.verticalAlignmentMode = .baseline
    labelNode.horizontalAlignmentMode = .center

    // Originally this function worked with labelNode.frame.height
    // But it depends on fontSize, so I decided to use it as a base
    var labelHeightShift = (labelFontSize - 1) / 2.0
    labelHeightShift -= 0.8  // empirical pixel perfect observation

    // Move the SKLabelNode to the center of the rectangle.
    labelNode.position = CGPoint(x: rect.midX, y: rect.midY - labelHeightShift)
}

请注意,我们将verticalAlignmentMode设置为.baseline。因此,我们需要自己计算labelHeightShift
是的,代码有点混乱,使用了0.8和其他常量。但我还没有找到更好的解决方案。
希望这能帮助到某些人。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接