实现对字符串的画线动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//
// ZYAnimationLayer.m
// ZYDrawString
//
// Created by soufun on 15-1-9.
// Copyright (c) 2015年 ZY. All rights reserved.
//

#import "ZYAnimationLayer.h"

@interface ZYAnimationLayer()
@property (nonatomic, retain) CAShapeLayer *pathLayer;
@property (nonatomic, retain) CALayer *penLayer;
@end

@implementation ZYAnimationLayer
+(void)createAnimationLayerWithString:(NSString*)string andRect:(CGRect)rect andView:(UIView *)view andFont:(UIFont*)ui_font andStrokeColor:(UIColor*)color
{
ZYAnimationLayer * animationLayer = [ZYAnimationLayer layer];
animationLayer.frame = rect;
[view.layer addSublayer:animationLayer];

if (animationLayer.pathLayer != nil) {
[animationLayer.penLayer removeFromSuperlayer];
[animationLayer.pathLayer removeFromSuperlayer];
animationLayer.pathLayer = nil;
animationLayer.penLayer = nil;
}
CTFontRef font =CTFontCreateWithName((CFStringRef)ui_font.fontName,
ui_font.pointSize,
NULL);
CGMutablePathRef letters = CGPathCreateMutable();

//这里设置画线的字体和大小
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)font, kCTFontAttributeName,
nil];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string
attributes:attrs];
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attrString);
CFArrayRef runArray = CTLineGetGlyphRuns(line);

// for each RUN
for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runArray); runIndex++)
{
// Get FONT for this run
CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex);
CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);

// for each GLYPH in run
for (CFIndex runGlyphIndex = 0; runGlyphIndex < CTRunGetGlyphCount(run); runGlyphIndex++)
{
CFRange thisGlyphRange = CFRangeMake(runGlyphIndex, 1);
CGGlyph glyph;
CGPoint position;
CTRunGetGlyphs(run, thisGlyphRange, &glyph);
CTRunGetPositions(run, thisGlyphRange, &position);

{
CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, NULL);
CGAffineTransform t = CGAffineTransformMakeTranslation(position.x, position.y);
CGPathAddPath(letters, &t, letter);
CGPathRelease(letter);
}
}
}
CFRelease(line);

UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointZero];
[path appendPath:[UIBezierPath bezierPathWithCGPath:letters]];

CGPathRelease(letters);
CFRelease(font);

CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = animationLayer.bounds;
pathLayer.bounds = CGPathGetBoundingBox(path.CGPath);
pathLayer.geometryFlipped = YES;
pathLayer.path = path.CGPath;
pathLayer.strokeColor = [color CGColor];
pathLayer.fillColor = nil;
pathLayer.lineWidth = 1.0f;
pathLayer.lineJoin = kCALineJoinBevel;
[animationLayer addSublayer:pathLayer];
animationLayer.pathLayer = pathLayer;

UIImage *penImage = [UIImage imageNamed:@"noun_project_347_2.png"];
CALayer *penLayer = [CALayer layer];
penLayer.contents = (id)penImage.CGImage;
penLayer.anchorPoint = CGPointZero;
penLayer.frame = CGRectMake(0.0f, 0.0f, penImage.size.width, penImage.size.height);
[pathLayer addSublayer:penLayer];
animationLayer.penLayer = penLayer;

[animationLayer.pathLayer removeAllAnimations];
[animationLayer.penLayer removeAllAnimations];

animationLayer.penLayer.hidden = NO;

CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = 5.0;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[animationLayer.pathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];

CAKeyframeAnimation *penAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
penAnimation.duration = 5.0;
penAnimation.path = animationLayer.pathLayer.path;
penAnimation.calculationMode = kCAAnimationPaced;
penAnimation.delegate = animationLayer;
[animationLayer.penLayer addAnimation:penAnimation forKey:@"position"];
}

- (void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
self.penLayer.hidden = YES;
}
@end
1
2


1
摘自:
1
<a target=_blank href="https://github.com/bjzhangyang/ZYDrawString" target="_blank" id="url_1" style="font-stretch: normal; font-family: 宋体, 'Lucida Grande', Geneva, Arial, Verdana, Tahoma, Arial, 微软雅黑, 黑体; text-decoration: none; color: rgb(34, 153, 234);">https://github.com/bjzhangyang/ZYDrawString</a>