【问题标题】:How to draw a text using CoreGrahpics & Core animation如何使用 CoreGrahpics 和 Core 动画绘制文本
【发布时间】:2018-08-11 17:43:39
【问题描述】:

我想实现这种类型的动画。请查看此网址

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

【问题讨论】:

  • 如果有人能推荐一个关于 CAShapeLayers 和一般动画的基本入门,我将不胜感激
  • 将该属性字符串转换为 CGPath 或 BezierPath。然后将该路径设置为 CAShapeLayer 并设置描边。使用 CABasicAnimation 为笔画设置动画,瞧..
  • 感谢您的回复。您能否提供任何需要动画的代码

标签: ios objective-c swift3 core-graphics swift4


【解决方案1】:

如果您想同时为多个字符的轮廓笔画制作动画,您可以:

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

这看起来像这样:

请注意: 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
}

【讨论】:

  • 我们如何添加框架来绘制文本?
  • 我想为字形显示一条路径。请帮助我如何为字符显示单行?
  • 我在目标 C 中进行了转换,但在将动画单独放入角色时遇到了问题。我在 self.charLayers { view.layer.addSublayer(layer) let animation = CABasicAnimation(keyPath: "strokeEnd") animation.fromValue = 0 animation.duration = 2.2 layer.add(animation, forKey: "charAnimation") } 你能帮我找出对应的目标 c 吗?
  • fromValue 在 Objective-C 中被声明为@property(nullable, strong) id fromValue;,参见CAAnimation.h。所以你需要写:animation.fromValue = @(0.0); 而不是分配 0。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-06
  • 2020-10-01
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多