【问题标题】:Swift: Draw text using UIBezierPath [closed]Swift:使用 UIBezierPath 绘制文本 [关闭]
【发布时间】:2020-04-02 15:10:42
【问题描述】:

由于我在谷歌上找不到任何正确的答案,所以问题出在: 我需要drawattributed string 的形状,最好使用UIBezierPath。有什么方法可以实现吗?

【问题讨论】:

  • “绘制属性字符串的形状”正是任何文本元素自动执行的操作(UILabel、NSAttributeString.draw(at:)、CTLineDraw 等)。所以我期待你的意思比这更具体。你打算用 UIBezierPath 做什么?从 NSAttributeString 到 UIBezierPath 绝对可以通过 Core Text 实现,但它需要一些工作,如果你想处理 NSAttributedString 可以做的所有事情,它会变得相当复杂,所以最好了解你是否真的需要所有这些,或者如果一个更简单的解决方案将满足您的需求。通常 CATextLayer 是最好的。
  • 我的目标是处理文本,就像处理图片一样。我希望能够修剪它,在中间切一个圆,弯曲等。
  • 如果你想把它当作一张图片,你不需要 UIBezierPath。那会让你的工作更加努力。您想将其渲染为图像并处理图像。修剪和切割最好使用蒙版完成,您可以使用 CGContext 或 CATextLayer 轻松完成。如果我不得不猜测你在做什么,我猜你真的想要一个 CATextLayer,因为它可以让你访问大量的遮罩和剪辑以及 CIFilter 操作。

标签: swift core-graphics nsattributedstring uibezierpath


【解决方案1】:

你最好的办法就是使用这样的东西。使用贝塞尔路径可能非常复杂,尤其是当您要绘制多个单词时。尝试以正确的顺序和相同的 y 位置绘制线条将需要大量的自定义工作和令人头疼的事情。 下面将画出您设置的任何单词。

var charLayers = [CAShapeLayer]()

  func drawText() {
        for layer in self.charLayers {
            layer.removeFromSuperlayer()
        }
        let font = [NSAttributedString.Key.font: UIFont(name: fontNameHEre, size: FontSizeHere)! ]
        let attributedString = NSMutableAttributedString(string: "myStringHere", attributes: font)
        let charPaths = self.characterPaths(attributedString: attributedString, position: CGPoint(x: 255, y: 632))

        self.charLayers = charPaths.map { path -> CAShapeLayer in
            let shapeLayer = CAShapeLayer()
            shapeLayer.fillColor = UIColor.clear.cgColor
            shapeLayer.strokeColor = UIColor.black.cgColor
            shapeLayer.lineWidth = lineWidth
            shapeLayer.path = path
            return shapeLayer
        }
}

结果将是您定义的字符串。会为你画出来的。

只要在需要绘图的地方调用函数drawText()

-------- 编辑

抱歉忘记添加重要功能

见下文

    func characterPaths(attributedString: NSAttributedString, position: CGPoint) -> [CGPath] {

    let line = CTLineCreateWithAttributedString(attributedString)

    guard let glyphRuns = CTLineGetGlyphRuns(line) as? [CTRun] else { return []}

    var characterPaths = [CGPath]()

    for glyphRun in glyphRuns {
        guard let attributes = CTRunGetAttributes(glyphRun) as? [String:AnyObject] else { continue }
        let font = attributes[kCTFontAttributeName as String] as! CTFont

        for index in 0..<CTRunGetGlyphCount(glyphRun) {
            let glyphRange = CFRangeMake(index, 1)

            var glyph = CGGlyph()
            CTRunGetGlyphs(glyphRun, glyphRange, &glyph)

            var characterPosition = CGPoint()
            CTRunGetPositions(glyphRun, glyphRange, &characterPosition)
            characterPosition.x += position.x
            characterPosition.y += position.y

            if let glyphPath = CTFontCreatePathForGlyph(font, glyph, nil) {
                var transform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: characterPosition.x, ty: characterPosition.y)
                if let charPath = glyphPath.copy(using: &transform) {
                    characterPaths.append(charPath)
                }
            }
        }
    }
    return characterPaths
}

【讨论】:

  • self.characterPaths() 是什么?
  • @koen 抱歉检查更新的答案
  • 这将支持足够的 NSAttributedString 以在许多情况下有用,但请记住有很多 NSAttributedString 属性它不处理,尤其是文本装饰(例如下划线、删除线和阴影)。
猜你喜欢
  • 2015-05-21
  • 1970-01-01
  • 1970-01-01
  • 2017-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多