前两天下载了一个Swift的HUD提示效果,偶然发现其中的提示效果上面的文字是动态书写的。感觉挺不错的,代码地址如下:
http://code.cocoachina.com/view/129442。
然后自己使用里面部分技术写了一个OC版的,
Demo地址:https://github.com/longitachi/WritingEffect/tree/master
效果图:
Swift具体实现(仅仅贴出NSString转UIBezierPath的方法,动画简单自己加,或者下载源码):
- class func bezierPathFrom(string:String) -> UIBezierPath{
- let paths = CGPathCreateMutable()
- let fontName = __CFStringMakeConstantString("SnellRoundhand")
- let fontRef:AnyObject = CTFontCreateWithName(fontName,18,nil)
- let attrString = NSAttributedString(string: string,attributes: [kCTFontAttributeName as String : fontRef])
- let line = CTLineCreateWithAttributedString(attrString as CFAttributedString)
- let runA = CTLineGetGlyphRuns(line)
- for (var runIndex = 0; runIndex < CFArrayGetCount(runA); runIndex++){
- let run = CFArrayGetValueAtIndex(runA,runIndex);
- let runb = unsafeBitCast(run,CTRun.self)
- let CTFontName = unsafeBitCast(kCTFontAttributeName,UnsafePointer<Void>.self)
- let runFontC = CFDictionaryGetValue(CTRunGetAttributes(runb),CTFontName)
- let runFontS = unsafeBitCast(runFontC,CTFont.self)
- let width = UIScreen.mainScreen().bounds.width
- var temp = 0
- var offset:CGFloat = 0.0
- for(var i = 0; i < CTRunGetGlyphCount(runb); i++){
- let range = CFRangeMake(i,1)
- let glyph:UnsafeMutablePointer<CGGlyph> = UnsafeMutablePointer<CGGlyph>.alloc(1)
- glyph.initialize(0)
- let position:UnsafeMutablePointer<CGPoint> = UnsafeMutablePointer<CGPoint>.alloc(1)
- position.initialize(CGPointZero)
- CTRunGetGlyphs(runb,range,glyph)
- CTRunGetPositions(runb,position);
- let temp3 = CGFloat(position.memory.x)
- let temp2 = (Int) (temp3 / width)
- let temp1 = 0
- if(temp2 > temp1){
- temp = temp2
- offset = position.memory.x - (CGFloat(temp) * width)
- }
- let path = CTFontCreatePathForGlyph(runFontS,glyph.memory,nil)
- let x = position.memory.x - (CGFloat(temp) * width) - offset
- let y = position.memory.y - (CGFloat(temp) * 80)
- var transform = CGAffineTransformMakeTranslation(x,y)
- CGPathAddPath(paths,&transform,path)
- glyph.destroy()
- glyph.dealloc(1)
- position.destroy()
- position.dealloc(1)
- }
- }
- let bezierPath = UIBezierPath()
- bezierPath.moveToPoint(CGPointZero)
- bezierPath.appendPath(UIBezierPath(CGPath: paths))
- return bezierPath
- }
根据Swift翻译的OC版本,实现如下:
- - (UIBezierPath *)transformToBezierPath:(NSString *)string
- {
- CGMutablePathRef paths = CGPathCreateMutable();
- CFStringRef fontNameRef = CFSTR("SnellRoundhand");
- CTFontRef fontRef = CTFontCreateWithName(fontNameRef,nil);
- NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string attributes:@{(__bridge NSString *)kCTFontAttributeName: (__bridge UIFont *)fontRef}];
- CTLineRef lineRef = CTLineCreateWithAttributedString((CFAttributedStringRef)attrString);
- CFArrayRef runArrRef = CTLineGetGlyphRuns(lineRef);
- for (int runIndex = 0; runIndex < CFArrayGetCount(runArrRef); runIndex++) {
- const void *run = CFArrayGetValueAtIndex(runArrRef,runIndex);
- CTRunRef runb = (CTRunRef)run;
- const void *CTFontName = kCTFontAttributeName;
- const void *runFontC = CFDictionaryGetValue(CTRunGetAttributes(runb),CTFontName);
- CTFontRef runFontS = (CTFontRef)runFontC;
- CGFloat width = [UIScreen mainScreen].bounds.size.width;
- int temp = 0;
- CGFloat offset = .0;
- for (int i = 0; i < CTRunGetGlyphCount(runb); i++) {
- CFRange range = CFRangeMake(i,1);
- CGGlyph glyph = 0;
- CTRunGetGlyphs(runb,&glyph);
- CGPoint position = CGPointZero;
- CTRunGetPositions(runb,&position);
- CGFloat temp3 = position.x;
- int temp2 = (int)temp3/width;
- CGFloat temp1 = 0;
- if (temp2 > temp1) {
- temp = temp2;
- offset = position.x - (CGFloat)temp;
- }
- CGPathRef path = CTFontCreatePathForGlyph(runFontS,glyph,nil);
- CGFloat x = position.x - (CGFloat)temp*width - offset;
- CGFloat y = position.y - (CGFloat)temp * 80;
- CGAffineTransform transform = CGAffineTransformMakeTranslation(x,y);
- CGPathAddPath(paths,path);
- CGPathRelease(path);
- }
- CFRelease(runb);
- CFRelease(runFontS);
- }
- UIBezierPath *bezierPath = [UIBezierPath bezierPath];
- [bezierPath moveToPoint:CGPointZero];
- [bezierPath appendPath:[UIBezierPath bezierPathWithCGPath:paths]];
- CGPathRelease(paths);
- CFRelease(fontNameRef);
- CFRelease(fontRef);
- return bezierPath;
- }