Skip to content

Instantly share code, notes, and snippets.

@yycking
Last active May 20, 2019 08:31
Show Gist options
  • Save yycking/65086afff38ac437d39b0035934af3f4 to your computer and use it in GitHub Desktop.
Save yycking/65086afff38ac437d39b0035934af3f4 to your computer and use it in GitHub Desktop.
手寫字
var charLayers = [CAShapeLayer]()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
for layer in self.charLayers {
layer.removeFromSuperlayer()
}
let stringAttributes = [ NSAttributedString.Key.font: UIFont(name: "Zapfino", size: 32.0)! ]
let attributedString = NSMutableAttributedString(string: "Hello world!", attributes: stringAttributes )
let charPaths = self.charactersPath(attributedString: attributedString)
let charSize = charPaths.bounds.size
let point = view.center
charPaths.apply(CGAffineTransform(translationX: point.x-charSize.width * 0.5, y: point.y*0.5))
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 2
shapeLayer.path = charPaths.cgPath
view.layer.addSublayer(shapeLayer)
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.duration = 2.2
shapeLayer.add(animation, forKey: "charAnimation")
}
func charactersPath(attributedString: NSAttributedString) -> UIBezierPath {
let line = CTLineCreateWithAttributedString(attributedString)
guard let glyphRuns = CTLineGetGlyphRuns(line) as? [CTRun] else { return UIBezierPath()}
let characterPaths = CGMutablePath()
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)
if let glyphPath = CTFontCreatePathForGlyph(font, glyph, nil) {
let transform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: characterPosition.x, ty: characterPosition.y)
characterPaths.addPath(glyphPath, transform: transform)
}
}
}
return UIBezierPath(cgPath: characterPaths)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment