使用
[@"I‘m 六弦琴殇" animateOnView:self.view atRect:CGRectMake(120, 20, 200, 200) forFont:[UIFont systemFontOfSize:30] withColor:[UIColor redColor] andDuration:8.0];
源码
UIBezierPath (TextPath)
@interface UIBezierPath (TextPath)
+ (UIBezierPath *)bezierPathWithText:(NSString *)text font:(UIFont *)font;
@end
@implementation UIBezierPath (TextPath)
+ (UIBezierPath *)bezierPathWithText:(NSString *)text font:(UIFont *)font {
CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)font.fontName, font.pointSize, NULL);
if (!ctFont) return nil;
NSDictionary *attrs = @{ (__bridge id)kCTFontAttributeName:(__bridge id)ctFont };
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:text attributes:attrs];
CFRelease(ctFont);
CTLineRef line = CTLineCreateWithAttributedString((__bridge CFTypeRef)attrString);
if (!line) return nil;
CGMutablePathRef cgPath = CGPathCreateMutable();
CFArrayRef runs = CTLineGetGlyphRuns(line);
for (CFIndex iRun = 0, iRunMax = CFArrayGetCount(runs); iRun < iRunMax; iRun++) {
CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, iRun);
CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);
for (CFIndex iGlyph = 0, iGlyphMax = CTRunGetGlyphCount(run); iGlyph < iGlyphMax; iGlyph++) {
CFRange glyphRange = CFRangeMake(iGlyph, 1);
CGGlyph glyph;
CGPoint position;
CTRunGetGlyphs(run, glyphRange, &glyph);
CTRunGetPositions(run, glyphRange, &position);
CGPathRef glyphPath = CTFontCreatePathForGlyph(runFont, glyph, NULL);
if (glyphPath) {
CGAffineTransform transform = CGAffineTransformMakeTranslation(position.x, position.y);
CGPathAddPath(cgPath, &transform, glyphPath);
CGPathRelease(glyphPath);
}
}
}
UIBezierPath *path = [UIBezierPath bezierPathWithCGPath:cgPath];
CGRect boundingBox = CGPathGetPathBoundingBox(cgPath);
CFRelease(cgPath);
CFRelease(line);
[path applyTransform:CGAffineTransformMakeScale(1.0, -1.0)];
[path applyTransform:CGAffineTransformMakeTranslation(0.0, boundingBox.size.height)];
return path;
}
@end
NSString(Animation)
@interface NSString(Animation)
- (void)animateOnView:(UIView *)aView atRect:(CGRect)aRect forFont:(UIFont *)aFont withColor:(UIColor *)aColor andDuration:(CGFloat)aDuration;
@end
@implementation NSString(Animation)
- (void)animateOnView:(UIView *)aView atRect:(CGRect)aRect forFont:(UIFont *)aFont withColor:(UIColor *)aColor andDuration:(CGFloat)aDuration
{
// 创建文字路径
UIBezierPath *path = [UIBezierPath bezierPathWithText:self font:aFont];
// 创建路径图层
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = aRect;
pathLayer.bounds = CGPathGetBoundingBox(path.CGPath);
pathLayer.geometryFlipped = NO;
pathLayer.path = path.CGPath;
pathLayer.strokeColor = [aColor CGColor];
pathLayer.fillColor = nil;
pathLayer.lineWidth = 1.0f;
pathLayer.lineJoin = kCALineJoinBevel;
[aView.layer addSublayer:pathLayer];
// 创建画笔图层
UIImage *penImage = [UIImage imageNamed:@"pencil.png"];
CALayer *penLayer = [CALayer layer];
penLayer.contents = (id)penImage.CGImage;
penLayer.anchorPoint = CGPointMake(0, 1);
penLayer.frame = CGRectMake(0.0f, 0.0f, penImage.size.width, penImage.size.height);
[pathLayer addSublayer:penLayer];
// 绘图动画
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];// strokeStart 是擦除效果
pathAnimation.duration = aDuration;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
pathAnimation.removedOnCompletion = YES;
[pathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
// 画笔动画
CAKeyframeAnimation *penAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
penAnimation.duration = aDuration;
penAnimation.path = path.CGPath;
penAnimation.calculationMode = kCAAnimationPaced;
penAnimation.removedOnCompletion = YES;
[penLayer addAnimation:penAnimation forKey:@"position"];
}
@end