CAShapeLayer文字動畫

文字動畫也是CAShapeLayer圖形動畫的一種,巧妙運(yùn)用文字動畫可以實現(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>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,214評論 4 61
  • 一、CAShapelayer 我們知道可以不使用圖片情況下利用CGpath去構(gòu)建任意形狀的陰影。其實我們也可...
    小貓仔閱讀 1,800評論 0 5
  • 動畫:CAAnimation使用 使用動畫來寫名字! 技術(shù)點 { // 先導(dǎo)進(jìn)#import 頭文件 使用CASh...
    Evan葉少閱讀 1,000評論 0 4
  • 架構(gòu)使用的語言知識 這幾年數(shù)據(jù)分析 迅速發(fā)展,我們也做了一個微數(shù)據(jù)分析工具。該產(chǎn)品已成功運(yùn)行三年,滿足日活百萬的企...
    CobubRazor閱讀 1,690評論 1 2
  • 自己一直都是喜歡操場的,愿意一圈一圈繞著走,好像永遠(yuǎn)都不知疲倦的樣子。 有好友同行自如聊天很愜意,更加理解朋友的想...
    緘默9閱讀 381評論 2 1

友情鏈接更多精彩內(nèi)容