ios - 使用 CGPaths 和 CAShapeLayers 动画绘制字母

标签 ios swift uikit core-animation cgpath

我目前正在使用这段代码来为角色绘制动画:

var path = UIBezierPath()


    var unichars = [UniChar]("J".utf16)
    var glyphs = [CGGlyph](count: unichars.count, repeatedValue: 0)

    let gotGlyphs = CTFontGetGlyphsForCharacters(font, &unichars, &glyphs, unichars.count)
    if gotGlyphs {
        let cgpath = CTFontCreatePathForGlyph(font, glyphs[0], nil)
         path = UIBezierPath(CGPath: cgpath!)

    }

从字符(在本例中为“J”)创建贝塞尔曲线路径。 Get path to trace out a character in an iOS UIFont

然后我创建一个 CAShapeLayer() 并向其添加动画。

 let layer = CAShapeLayer()
   layer.position = //CGPoint
    layer.bounds = //CGRect()
    view.layer.addSublayer(layer)

    layer.path = path.CGPath

    layer.lineWidth = 5.0
    layer.strokeColor = UIColor.blackColor().CGColor
    layer.fillColor = UIColor.clearColor().CGColor
    layer.geometryFlipped = true

    layer.strokeStart = 0.0
    layer.strokeEnd = 1.0

    let anim = CABasicAnimation(keyPath: "strokeEnd")
    anim.duration = 8.0
    anim.fromValue = 0.0
    anim.toValue = 1.0

    layer.addAnimation(anim, forKey: nil)

结果是我选择的角色被正确地动画化了。但是,当我使用 .appendPath() 将另一条路径添加到 path 时,附加路径会如您所料直接添加到原始路径上。如果我想画一个所有字符都有适当间距等的字母,我该怎么办? 感谢您的宝贵时间。

最佳答案

您可以在路径上使用翻译(使用 CGAffineTransformMakeTranslation)来做到这一点,因为路径没有“位置”,它只是一组点。但是要在字符的每次迭代中进行转换,我们需要路径的当前宽度 - 我们可以为此使用 CGPathGetBoundingBox(),它获取路径将覆盖的框。所以有了我们需要的一切,我们就可以做一个例子。为整个单词创建一个路径是这样的:

let word = "Test"
let path = UIBezierPath()
let spacing: CGFloat = 50
var i: CGFloat = 0
for letter in word.characters {
    let newPath = getPathForLetter(letter)
    let actualPathRect = CGPathGetBoundingBox(path.CGPath)
    let transform = CGAffineTransformMakeTranslation((CGRectGetWidth(actualPathRect) + min(i, 1)*spacing), 0)
    newPath.applyTransform(transform)
    path.appendPath(newPath)
    i++
}

其中函数 getPathForLetter() 只是:

func getPathForLetter(letter: Character) -> UIBezierPath {
    var path = UIBezierPath()
    let font = CTFontCreateWithName("HelveticaNeue", 64, nil)
    var unichars = [UniChar]("\(letter)".utf16)
    var glyphs = [CGGlyph](count: unichars.count, repeatedValue: 0)

    let gotGlyphs = CTFontGetGlyphsForCharacters(font, &unichars, &glyphs, unichars.count)
    if gotGlyphs {
        let cgpath = CTFontCreatePathForGlyph(font, glyphs[0], nil)
        path = UIBezierPath(CGPath: cgpath!)
    }

    return path
}

关于ios - 使用 CGPaths 和 CAShapeLayers 动画绘制字母,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34465201/

相关文章:

ios - 如何在 Swift 中处理多个 UIButton 上的点击

ios - 自定义透明UITabBar

ios - UILabel 中的 NSAttributedString 是否会忽略标签的 numberOfLines 属性?

ios - 如何在 iOS SDK 中使用语音识别?

android - 检测 scrollview 是否到达底部 titanium

objective-c - UITableView 像联系人应用程序编辑模式

ios - 使用分发证书发出测试推送通知

ios - 访问导致快速崩溃的按钮操作内的单元格

ios - IOS 开发新手,点击评论单元格 Thread 1 : signal SIGABRT and terminating app due to uncaught exception 时崩溃

ios - NSFetchedResultsController - TableView 中的不完整 UI 更新