给对本文感兴趣的朋友们推荐个好东西:paintcode
动画预览先扯淡
最近手痒又想整点动画玩玩,但是想了几个主意发现稍微复杂一点的手写都一定会累爆。这篇文章记录一下今天折腾的一个方案。说来简单,就是用矢量设计工具舒舒服服的做好设计,然后输出成 svg 格式,再用 NSXMLParser
去读出来,转换成 UIBezIErPath
,然后就天高任鸟飞~
清晰起见,这里不使用各种库,由上面的二维码动画为例,只转换最简单的矩形。需要更多高能 *** 作的,出门右转 SVGKit。
开工筹备材料先,首先找个能提供 svg 格式下载的二维码生成网站,比如 这个 。拿到 svg 文件后用文本编辑器打开可以看到其实是一个描述矢量图形的 xml ,而且里面几百个矩形。。。如果你用的生成网站跟我一样,还会有一个白色的背景矩形,待会儿我们会把它排除掉。
准备工作就到这了,接下来我们会用 NSXMLParser
来解析这个二维码。
新建一个 Single VIEw Application
,把二维码拖进项目里去,在 VIEwController
里添加一个 UIVIEw
作为二维码的容器:
class VIEwController: UIVIEwController { let qrVIEw = UIVIEw() overrIDe func vIEwDIDLoad() { super.vIEwDIDLoad() qrVIEw.center = vIEw.center vIEw.addSubvIEw(qrVIEw) } ...}
初始化一个 NSXMLParser
去解析 svg ,同时让 VIEwController
实现 NSXMLParserDelegate
的 `
parser(_:dIDStartElement:namespaceURI:qualifIEdname:attributes:) 和
parserDIDEnddocument(_:)`
两个方法用于处理解析结果:
class VIEwController: UIVIEwController,NSXMLParserDelegate { ... overrIDe func vIEwDIDLoad() { ... let qrPath = NSBundle.mainBundle().pathForResource("zcfan_qrcode",ofType: "svg")! let qrData = NSData(contentsOffile: qrPath) let xmlParser = NSXMLParser(data: qrData) xmlParser.delegate = self xmlParser.parse() } func parser(parser: NSXMLParser!,dIDStartElement elementname: String!,namespaceURI: String!,qualifIEdname qname: String!,attributes attributeDict: [NSObject : AnyObject]!) { // 每当解析到一个新标签,这里就会被调用 } func parserDIDEnddocument(parser: NSXMLParser!) { // 整个 svg 文件解析完毕后,这里就会被调用 } ...}
接下来我们会在 parser(_:dIDStartElement:namespaceURI:qualifIEdname:attributes:)
中把遇到的每一个形如:
<rect ... x="0" y="0" wIDth="12" height="12" fill="black"/>
的标签转换成 CGRect
保存在数组中,并在 parserDIDEnddocument(_:)
中把他们转换为 CAShapeLayer
并添加动画。
先来看看 parser(_:dIDStartElement:namespaceURI:qualifIEdname:attributes:)
的内容:
...var rects = [CGRect]() // 用于存储二维码func parser(parser: NSXMLParser!,attributes attributeDict: [NSObject : AnyObject]!) { // 只转换 “黑色” 的二维码 “方块” if elementname == "rect" && (attributeDict["fill"] as String) == "black" { let x = (attributeDict["x"] as Nsstring).doubleValue let y = (attributeDict["y"] as Nsstring).doubleValue let w = (attributeDict["wIDth"] as Nsstring).doubleValue let h = (attributeDict["height"] as Nsstring).doubleValue let rect = CGRect(x: x,y: y,wIDth: w,height: h) rects.append(rect) // 设置 qrVIEw 的尺寸为 svg 图像的大小 } else if elementname == "svg" { let w = (attributeDict["wIDth"] as Nsstring).doubleValue let h = (attributeDict["height"] as Nsstring).doubleValue qrVIEw.bounds = CGRect(x: 0,y: 0,height: h) }}...
接下来是 parserDIDEnddocument(_:)
,在这里我们要把二维码显示出来:
...func parserDIDEnddocument(parser: NSXMLParser!) { for r in rects { let rectLayer = CAShapeLayer() rectLayer.fillcolor = UIcolor.darkGraycolor().CGcolor rectLayer.strokecolor = nil rectLayer.path = UIBezIErPath(rect: CGRect(origin: CGPointZero,size: r.size)).CGPath // #1 rectLayer.frame = r // #2 qrVIEw.layer.addSublayer(rectLayer) }}...
#1、#2 :看着有点晕?代码不直观的话不妨稍微把玩一下,原因很简单,但要用语言解释我的舌头可能会打结。。。
至此,运行项目应该就能在屏幕上看到一个大二维码了!
加特技! Duang~回到上面的 parserDIDEnddocument(_:)
方法,然后把它改到面目全非!Duang~
func parserDIDEnddocument(parser: NSXMLParser!) { qrVIEw.layer.shadowcolor = UIcolor.graycolor().CGcolor qrVIEw.layer.shadowRadius = 4 qrVIEw.layer.shadowOpacity = 1 qrVIEw.layer.shadowOffset = CGSizeZero for r in rects { let rectLayer = CAShapeLayer() rectLayer.fillcolor = UIcolor.darkGraycolor().CGcolor rectLayer.strokecolor = nil rectLayer.path = UIBezIErPath(rect: CGRect(origin: CGPointZero,size: r.size)).CGPath rectLayer.frame = r var starttransform = CAtransform3DIDentity starttransform.m34 = 1.0 / -20 // 透视 starttransform = CAtransform3DRotate(starttransform,CGfloat(M_PI)*0.5,1,0) // 沿 y 轴旋转 π/2 圈,待会再动画转回来 // transform 动画 let transAnim = CABasicAnimation(keyPath: "transform") transAnim.duration = drand48() * 4 // 随机一个持续时间 transAnim.fromValue = NSValue(CAtransform3D: starttransform) transAnim.tovalue = NSValue(CAtransform3D: CAtransform3DIDentity) rectLayer.addAnimation(transAnim,forKey: "transAnim") // 透明度动画 let AlphaAnim = CABasicAnimation(keyPath: "opacity") AlphaAnim.duration = transAnim.duration AlphaAnim.fromValue = 0 AlphaAnim.tovalue = 1 rectLayer.addAnimation(AlphaAnim,forKey: "AlphaAnim") qrVIEw.layer.addSublayer(rectLayer) }}完工
没眼看,不录gif了。。。心塞。。。
继续加特技手贱没忍住。。。二维码真是玩不坏。。。
总结
以上是内存溢出为你收集整理的[swift]读取svg图片为UIBezierPath,开心做动画全部内容,希望文章能够帮你解决[swift]读取svg图片为UIBezierPath,开心做动画所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)