关于这个问题,我已经在另一篇blog中有所提及:
CoreText精彩文字轮廓绘制动画的一点改进
不过原有的转换代码使用Obj-C写的,在这里我们尝试将其转换为Swift语言,然后利用它实现一个测试小程序.
首先贴出原来Objc的代码:
- (voID) setupTextLayer{ if (self.pathLayer != nil) { [self.penLayer removeFromSuperlayer]; [self.pathLayer removeFromSuperlayer]; self.pathLayer = nil; self.penLayer = nil; } // Create path from text // See: http://www.codeproject.com/KB/iPhone/Glyph.aspx // license: The Code Project Open license (CPol) 1.02 http://www.codeproject.com/info/cpol10.aspx CGMutablePathref letters = CGPathCreateMutable(); CTFontRef Font = CTFontCreateWithname(CFSTR("Helvetica-Bold"),72.0f,NulL); NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys: (ID)Font,kCTFontAttributename,nil]; NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"你好,大熊猫侯佩!" //NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"Hello World!" 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++) { // get Glyph & Glyph-data CFRange thisGlyphRange = CFRangeMake(runGlyphIndex,1); CGGlyph glyph; CGPoint position; CTRunGetGlyphs(run,thisGlyphRange,&glyph); CTRunGetpositions(run,&position); // Get PATH of outline { 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 = self.animationLayer.bounds; pathLayer.bounds = CGPathGetBoundingBox(path.CGPath); //pathLayer.backgroundcolor = [[UIcolor yellowcolor] CGcolor]; pathLayer.geometryFlipped = YES; pathLayer.path = path.CGPath; pathLayer.strokecolor = [[UIcolor blackcolor] CGcolor]; pathLayer.fillcolor = nil; pathLayer.linewidth = 5.0f; //pathLayer.lineJoin = kCAlineJoinBevel; pathLayer.lineJoin = kCAlineJoinMiter; [self.animationLayer addSublayer:pathLayer]; self.pathLayer = pathLayer; //happy commit NSLog(@"Hello World!!!"); //UIImage *penImage = [UIImage imagenamed:@"noun_project_347_2.png"]; UIImage *penImage = [UIImage imagenamed:@"bee.png"]; CALayer *penLayer = [CALayer layer]; penLayer.contents = (ID)penImage.CGImage; penLayer.anchorPoint = CGPointZero; penLayer.frame = CGRectMake(0.0f,0.0f,penImage.size.wIDth/5,penImage.size.height/5); [pathLayer addSublayer:penLayer]; self.penLayer = penLayer;}
看起来颇长啊!不过不要太在意,因为我们要用Swift重写的代码只提取其中中间的一部分,这样可以更好的重用.
新建一个项目,基于Swift语言.
在项目中新建一个Swift源代码文件,该文件扩展了String类,我们在其扩展中先写一个帮助方法的存根:
extension String{ func topath(Font:CTFont)->CGPath{ }}
topath方法用来实现任意String实例到CGPath路径的转换,在其中添加如下内容:
let letters:CGMutablePathref = CGPathCreateMutable() let attrs = [kCTFontAttributename as String:Font] let attrString:NSAttributedString = NSAttributedString(string: self,attributes: attrs) let line:CTline = CTlineCreateWithAttributedString(attrString) let runArray = CTlineGetGlyphRuns(line) for runIndex in 0..<CFArrayGetCount(runArray){ let run = CFArrayGetValueAtIndex(runArray,runIndex) let runb = unsafeBitCast(run,CTRun.self) //let runFont:CTFont = CFDictionaryGetValue(CTRunGetAttributes(runb),kCTFontAttributename as String) as! CTFont let CTFontname = unsafeBitCast(kCTFontAttributename,UnsafePointer<VoID>.self) let runFontC = CFDictionaryGetValue(CTRunGetAttributes(runb),CTFontname) let runFont = unsafeBitCast(runFontC,CTFont.self) //for each GLYPH in run for runGlyphIndex in 0..<CTRunGetGlyphCount(runb){ //get Glyph & Glyph-data let glyphRange = CFRange(location: runGlyphIndex,length: 1) //let glyph:UnsafeMutablePointer<CGGlyph> = UnsafeMutablePointer<CGGlyph>.alloc(1) //glyph.initialize(0) var glyph:CGGlyph = 0 let position:UnsafeMutablePointer<CGPoint> = UnsafeMutablePointer<CGPoint>.alloc(1) position.initialize(CGPoint.zero) CTRunGetGlyphs(runb,glyphRange,&glyph) CTRunGetpositions(runb,position) //Get PATH of outline //let letter = CTFontCreatePathForGlyph(runFont,glyph.memory,nil) let letter = CTFontCreatePathForGlyph(runFont,nil) var t = CGAffinetransformMakeTranslation(position.memory.x,position.memory.y) //let tx:UnsafeMutablePointer<CGAffinetransform> = UnsafeMutablePointer<CGAffinetransform>.alloc(1) //tx.initialize(t) CGPathAddpath(letters,letter) //CGPathRelease(letter) position.destroy() position.dealloc(1) } } let path = UIBezIErPath() path.movetoPoint(CGPoint.zero) path.appendpath(UIBezIErPath(CGPath: letters)) return path.CGPath
大家可以对照原来的Obj-c版本看一下,大致都是一一对应的,只有少数几个涉及 *** 作C语言数据的地方有修改,大家可以参考我写的另一篇blog:
Swift中如何转换不同类型的Mutable指针
核心功能有了,下面就好办了!我们想要的是点击屏幕开始显示动画,于是重载如下方法:
overrIDe func touchesEnded(touches: Set<UItouch>,withEvent event: UIEvent?) { if isAnimating { return } isAnimating = true flyerLayer.opacity = 0.8 pathLayer.removeAllAnimations() flyerLayer.removeAllAnimations() let strokeAnimation = CABasicAnimation(keyPath: "strokeEnd") strokeAnimation.duration = 20.0 strokeAnimation.fromValue = 0.0 strokeAnimation.tovalue = 1.0 strokeAnimation.delegate = self pathLayer.addAnimation(strokeAnimation,forKey: nil) let flyAnimation = CAKeyframeAnimation(keyPath: "position") flyAnimation.duration = 20.0 flyAnimation.path = pathLayer.path flyAnimation.calculationMode = kCAAnimationPaced flyerLayer.addAnimation(flyAnimation,forKey: nil) }
下面是App实际运行的效果:
总结以上是内存溢出为你收集整理的将String转换为其表示的路径画到屏幕上全部内容,希望文章能够帮你解决将String转换为其表示的路径画到屏幕上所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)