文字動畫也是CAShapeLayer
圖形動畫的一種实束,巧妙運用文字動畫可以實現(xiàn)很不錯的效果,比如半糖app的下拉動畫逊彭。本文就主要講一下其實現(xiàn)原理咸灿。
文字動畫主要分為兩部分:
- 將文字轉(zhuǎn)化為
CAShapeLayer
- 通過更改
CAShapeLayer
的StrokeEnd屬性值生成動畫
將文字轉(zhuǎn)換為CAShapeLayer
將文字轉(zhuǎn)換為CAShapeLayer
的過程比較復(fù)雜,可以細(xì)分為以下幾個步驟:
- 創(chuàng)建
NSAttributedString
并生成CTLineRef
- 使用
CTLineRef
生成CTRunRef
數(shù)組 - 遍歷
CTRunRef
數(shù)組侮叮,得到每個CTRunRef
- 遍歷
CTRunRef
中每個長度為1的區(qū)間生成CGGlyph
并轉(zhuǎn)換為CGPath
路徑避矢,將所有路徑拼接起來 - 創(chuàng)建
ShapeLayer
并將生成的路徑賦值給該ShapeLayer
以下是每個步驟的實現(xiàn)方式:
創(chuàng)建NSAttributedString并生成CTLineRef
// 定義字體屬性
CTFontRef font = CTFontCreateWithName(CFSTR("HelveticaNeue-UltraLight"), fontSize, NULL);
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)font, kCTFontAttributeName,nil];
// 創(chuàng)建NSAttributedString
NSAttributedString *str = [[NSAttributedString alloc] initWithString:text attributes:attrs];
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)str);
使用CTLineRef生成CTRunRef數(shù)組
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)str);
CFArrayRef runArray = CTLineGetGlyphRuns(line);
遍歷CTRunRef數(shù)組,得到每個CTRunRef
for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runArray); runIndex++) {
//
CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex);
CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);
}
遍歷CTRunRef中每個長度為1的區(qū)間生成CGGlyph并轉(zhuǎn)換為CGPath路徑囊榜,將所有路徑拼接起來
for (CFIndex glyphIndex = 0; glyphIndex < CTRunGetGlyphCount(run); glyphIndex++) {
CGGlyph glyph;
CGPoint position;
CFRange currentRange = CFRangeMake(glyphIndex, 1);
CTRunGetGlyphs(run, currentRange, &glyph);
CTRunGetPositions(run, currentRange, &position);
CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, NULL);
CGAffineTransform t = CGAffineTransformMakeTranslation(position.x, position.y);
CGPathAddPath(letters, &t, letter);
CGPathRelease(letter);
}
創(chuàng)建ShapeLayer并將生成的路徑賦值給該ShapeLayer
// 創(chuàng)建UIBezierPath
UIBezierPath *path = [UIBezierPath bezierPathWithCGPath:letters];
// 創(chuàng)建并配置CAShapeLayer
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = self.bounds;
pathLayer.bounds = CGPathGetBoundingBox(path.CGPath);
pathLayer.geometryFlipped = YES;
pathLayer.path = path.CGPath;
pathLayer.strokeColor = fontColor.CGColor;
pathLayer.fillColor = nil;
pathLayer.lineWidth = 1.0f;
pathLayer.lineJoin = kCALineJoinBevel;
pathLayer.strokeStart = 0;
pathLayer.strokeEnd = 0;
最后审胸,將ShapeLayer添加到動畫圖層中就行了
生成文字動畫
通過改變ShapeLayer的StrokeEnd屬性值就可以生成文字動畫
添加Slider
- (void)setupSlider {
CGFloat leftMargin = 20;
UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(leftMargin, kMainHeight - 30, kMainWidth - leftMargin * 2, 3)];
slider.minimumValue = 0;
slider.maximumValue = 1;
[self.view addSubview:slider];
[slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged];
}
實現(xiàn)Slider的ValueChange方法
- (void)sliderValueChanged:(UISlider *)sender {
self.pathLayer.strokeEnd = sender.value;
}
至此,一個文字動畫就完成了
本文demo的github地址:<a>https://github.com/zephyrw/TextAnimationDemo.git</a>