ios - 如何使用 CoreGrahpics 和 Core 动画绘制文本

标签 ios objective-c swift3 core-graphics swift4

我想实现这种类型的动画。请检查这个 URL

https://www.dropbox.com/s/gz9vfy5refsh7a5/Screen.mov?dl=0

我正在添加我在项目中使用的代码,在该项目中我使用 Core Graphics 来渲染带有动画的文本,但我无法为上述链接中显示的文本设置动画

这是我用来在屏幕上呈现文本的代码

    let context = UIGraphicsGetCurrentContext()!
    context.saveGState()
    context.setAlpha(noLightText)

    let nOLIGHTRect = CGRect(x: 145.66, y: 590, width: 449.38, height: 125)
    let nOLIGHTStyle = NSMutableParagraphStyle()
    nOLIGHTStyle.alignment = .center
    let nOLIGHTFontAttributes = [
        .font: UIFont(name: "Futura-CondensedExtraBold", size: 96)!,
        .foregroundColor: nOLIGHTColor,
        .paragraphStyle: nOLIGHTStyle,
        ] as [NSAttributedStringKey: Any]

    "NO LIGHT".draw(in: nOLIGHTRect, withAttributes: nOLIGHTFontAttributes)

    context.restoreGState()


    //// LOW LIGHT Drawing
    context.saveGState()
    context.setAlpha(_0)

    let lOWLIGHTRect = CGRect(x: 145.94, y: 590, width: 449.38, height: 125)
    let lOWLIGHTStyle = NSMutableParagraphStyle()
    lOWLIGHTStyle.alignment = .left
    let lOWLIGHTFontAttributes = [
        .font: UIFont(name: "Futura-CondensedExtraBold", size: 96)!,
        .foregroundColor: lOWLIGHTColor,
        .paragraphStyle: lOWLIGHTStyle,
        ] as [NSAttributedStringKey: Any]

    "LOW LIGHT".draw(in: lOWLIGHTRect, withAttributes: lOWLIGHTFontAttributes)

    context.restoreGState()


    //// MID LIGHT Drawing
    context.saveGState()
    context.setAlpha(mediumLightText)

    let mIDLIGHTRect = CGRect(x: 145.77, y: 590, width: 449.38, height: 125)
    let mIDLIGHTStyle = NSMutableParagraphStyle()
    mIDLIGHTStyle.alignment = .left
    let mIDLIGHTFontAttributes = [
        .font: UIFont(name: "Futura-CondensedExtraBold", size: 96)!,
        .foregroundColor: mIDLIGHTColor,
        .paragraphStyle: mIDLIGHTStyle,
        ] as [NSAttributedStringKey: Any]


    "MID LIGHT".draw(in: mIDLIGHTRect, withAttributes: mIDLIGHTFontAttributes)

    context.restoreGState()

最佳答案

如果您想一次为多个字符的轮廓笔画设置动画,您可以:

  • 确定每个字符的 CGPaths
  • 将 CGPaths 映射到 CAShapeLayers
  • strokeEnd 属性设置动画

这看起来像这样: animated text

请注意: iOS 使用的字体是使用 TrueType 或 OpenType 格式的轮廓字体。这意味着每个字形都使用直线和曲线来定义其边界。我们通常在渲染字形时看到的是填充区域。因此,如果“strokeEnd”属性是动画的,则绘制字形的轮廓。以下代码显示了如何实现这一目标。

以人类编写文本的方式对文本进行动画处理会更加费力(例如,使用笔划字体而不是轮廓字体加上关联的引擎或使用用户定义的矢量路径来表示每个字符)

var charLayers = [CAShapeLayer]()

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    for layer in self.charLayers {
        layer.removeFromSuperlayer()
    }

    let stringAttributes = [ NSAttributedStringKey.font: UIFont(name: "Futura-CondensedExtraBold", size: 64.0)! ]
    let attributedString = NSMutableAttributedString(string: "hello world", attributes: stringAttributes )
    let charPaths = self.characterPaths(attributedString: attributedString, position: CGPoint(x: 24, y: 192))

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

    for layer in self.charLayers {
        view.layer.addSublayer(layer)
        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.fromValue = 0
        animation.duration = 2.2
        layer.add(animation, forKey: "charAnimation")
    }
}

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
}

关于ios - 如何使用 CoreGrahpics 和 Core 动画绘制文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49087257/

相关文章:

ios - 应用程序在后台时本地通知声音不播放 - Swift

iphone - iOS:在 UIWebView 中从 URL 加载音频时出现问题

iphone - 如何使用 NSHTTPURLResponse 在 iPhone 上通过 HTTP 查询文件的最后修改日期?

ios - 亚马逊 MWS 产品 API 返回 401 错误 "Access denied"

ios - 在ContainerView中打开不同的 View

ios - 如何比较 Swift 3 中的 UIViewController?

ios - 如果应用商店没有得到 30% 的提成,他们会批准应用程序吗?

ios - 动画状态栏 iOS 7

ios - 如何在init函数中实例化一个依赖self的对象?

ios - 尝试通过递归从 Firebase 加载时出错