(Swift+iOS)字符串轨迹转贝塞尔曲线,实现动态写字效果

前端之家收集整理的这篇文章主要介绍了(Swift+iOS)字符串轨迹转贝塞尔曲线,实现动态写字效果前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

前两天下载了一个Swift的HUD提示效果,偶然发现其中的提示效果上面的文字是动态书写的。感觉挺不错的,代码地址如下:

http://code.cocoachina.com/view/129442。

然后自己使用里面部分技术写了一个OC版的,

Demo地址:https://github.com/longitachi/WritingEffect/tree/master

效果图:



Swift具体实现(仅仅贴出NSString转UIBezierPath的方法,动画简单自己加,或者下载源码):

  1. class func bezierPathFrom(string:String) -> UIBezierPath{
  2. let paths = CGPathCreateMutable()
  3. let fontName = __CFStringMakeConstantString("SnellRoundhand")
  4. let fontRef:AnyObject = CTFontCreateWithName(fontName,18,nil)
  5. let attrString = NSAttributedString(string: string,attributes: [kCTFontAttributeName as String : fontRef])
  6. let line = CTLineCreateWithAttributedString(attrString as CFAttributedString)
  7. let runA = CTLineGetGlyphRuns(line)
  8. for (var runIndex = 0; runIndex < CFArrayGetCount(runA); runIndex++){
  9. let run = CFArrayGetValueAtIndex(runA,runIndex);
  10. let runb = unsafeBitCast(run,CTRun.self)
  11. let CTFontName = unsafeBitCast(kCTFontAttributeName,UnsafePointer<Void>.self)
  12. let runFontC = CFDictionaryGetValue(CTRunGetAttributes(runb),CTFontName)
  13. let runFontS = unsafeBitCast(runFontC,CTFont.self)
  14. let width = UIScreen.mainScreen().bounds.width
  15. var temp = 0
  16. var offset:CGFloat = 0.0
  17. for(var i = 0; i < CTRunGetGlyphCount(runb); i++){
  18. let range = CFRangeMake(i,1)
  19. let glyph:UnsafeMutablePointer<CGGlyph> = UnsafeMutablePointer<CGGlyph>.alloc(1)
  20. glyph.initialize(0)
  21. let position:UnsafeMutablePointer<CGPoint> = UnsafeMutablePointer<CGPoint>.alloc(1)
  22. position.initialize(CGPointZero)
  23. CTRunGetGlyphs(runb,range,glyph)
  24. CTRunGetPositions(runb,position);
  25. let temp3 = CGFloat(position.memory.x)
  26. let temp2 = (Int) (temp3 / width)
  27. let temp1 = 0
  28. if(temp2 > temp1){
  29. temp = temp2
  30. offset = position.memory.x - (CGFloat(temp) * width)
  31. }
  32. let path = CTFontCreatePathForGlyph(runFontS,glyph.memory,nil)
  33. let x = position.memory.x - (CGFloat(temp) * width) - offset
  34. let y = position.memory.y - (CGFloat(temp) * 80)
  35. var transform = CGAffineTransformMakeTranslation(x,y)
  36. CGPathAddPath(paths,&transform,path)
  37. glyph.destroy()
  38. glyph.dealloc(1)
  39. position.destroy()
  40. position.dealloc(1)
  41. }
  42. }
  43. let bezierPath = UIBezierPath()
  44. bezierPath.moveToPoint(CGPointZero)
  45. bezierPath.appendPath(UIBezierPath(CGPath: paths))
  46. return bezierPath
  47. }

根据Swift翻译的OC版本,实现如下:
  1. - (UIBezierPath *)transformToBezierPath:(NSString *)string
  2. {
  3. CGMutablePathRef paths = CGPathCreateMutable();
  4. CFStringRef fontNameRef = CFSTR("SnellRoundhand");
  5. CTFontRef fontRef = CTFontCreateWithName(fontNameRef,nil);
  6. NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string attributes:@{(__bridge NSString *)kCTFontAttributeName: (__bridge UIFont *)fontRef}];
  7. CTLineRef lineRef = CTLineCreateWithAttributedString((CFAttributedStringRef)attrString);
  8. CFArrayRef runArrRef = CTLineGetGlyphRuns(lineRef);
  9. for (int runIndex = 0; runIndex < CFArrayGetCount(runArrRef); runIndex++) {
  10. const void *run = CFArrayGetValueAtIndex(runArrRef,runIndex);
  11. CTRunRef runb = (CTRunRef)run;
  12. const void *CTFontName = kCTFontAttributeName;
  13. const void *runFontC = CFDictionaryGetValue(CTRunGetAttributes(runb),CTFontName);
  14. CTFontRef runFontS = (CTFontRef)runFontC;
  15. CGFloat width = [UIScreen mainScreen].bounds.size.width;
  16. int temp = 0;
  17. CGFloat offset = .0;
  18. for (int i = 0; i < CTRunGetGlyphCount(runb); i++) {
  19. CFRange range = CFRangeMake(i,1);
  20. CGGlyph glyph = 0;
  21. CTRunGetGlyphs(runb,&glyph);
  22. CGPoint position = CGPointZero;
  23. CTRunGetPositions(runb,&position);
  24. CGFloat temp3 = position.x;
  25. int temp2 = (int)temp3/width;
  26. CGFloat temp1 = 0;
  27. if (temp2 > temp1) {
  28. temp = temp2;
  29. offset = position.x - (CGFloat)temp;
  30. }
  31. CGPathRef path = CTFontCreatePathForGlyph(runFontS,glyph,nil);
  32. CGFloat x = position.x - (CGFloat)temp*width - offset;
  33. CGFloat y = position.y - (CGFloat)temp * 80;
  34. CGAffineTransform transform = CGAffineTransformMakeTranslation(x,y);
  35. CGPathAddPath(paths,path);
  36. CGPathRelease(path);
  37. }
  38. CFRelease(runb);
  39. CFRelease(runFontS);
  40. }
  41. UIBezierPath *bezierPath = [UIBezierPath bezierPath];
  42. [bezierPath moveToPoint:CGPointZero];
  43. [bezierPath appendPath:[UIBezierPath bezierPathWithCGPath:paths]];
  44. CGPathRelease(paths);
  45. CFRelease(fontNameRef);
  46. CFRelease(fontRef);
  47. return bezierPath;
  48. }

猜你在找的Swift相关文章