iOS 显示SVG文件的方法
1. Swift iOS : 显示SVG文件的方法
SVG文件是矢量图标准之一,特点是可以缩放,并且可以用可以阅读的源代码的方式(而不是二进制)来存储图形信息。比如如下文件就是一个svg文件:<svgxmlns=“http://www.w3.org/2000/svg"viewBox="00350100”> <markerid="arrowhead"markerWidth="10"markerHeight=&q
SVG文件是矢量图标准之一,特点是可以缩放,并且可以用可以阅读的源代码的方式(而不是二进制)来存储图形信息。比如如下文件就是一个svg文件:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 100">
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7"
refX="0" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" />
</marker>
</defs>
<line x1="0" y1="50" x2="250" y2="50" stroke="#000"
stroke-width="8" marker-end="url(#arrowhead)" />
</svg>
它是一个箭头图。可以使用UIWebView视图加载此文件并显示。首先把SVG文件作为资源文件加入工程,命名为1.svg。
其实,使用如下代码加载此文件:
var path: String = Bundle.main.path(forResource: "1", ofType: "svg")!
var url: NSURL = NSURL.fileURL(withPath: path) as NSURL
var request: NSURLRequest = NSURLRequest(url: url as URL)
webview?.loadRequest(request as URLRequest)
完整代码如下:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let page = Page()
page.view.backgroundColor = .blue
self.window!.rootViewController = page
self.window?.makeKeyAndVisible()
return true
}
}
class Page: UIViewController {
var count = 0
var webview : UIWebView!
var webview1 : UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
webview = UIWebView()
webview?.frame = CGRect(x: 0, y: 100, width: 100, height: 100)
view.addSubview(webview!)
webview1 = UIWebView()
webview1.frame = CGRect(x: 0, y: 200, width: 50, height: 50)
view.addSubview(webview1!)
let path: String = Bundle.main.path(forResource: "1", ofType: "svg")!
let url: NSURL = NSURL.fileURL(withPath: path) as NSURL
let request: NSURLRequest = NSURLRequest(url: url as URL)
webview?.loadRequest(request as URLRequest)
webview1.loadRequest(request as URLRequest)
}
}
2. 使用工具SVGKit解析SVG文件
SVGKit下载源码地址:点击这里下载SVGKit源码
2.1 SVGKit使用
我们按照正常的swift创建我们的项目,然后我们按照我们的GitHub的要求(Build the static library),这里我就不翻译了其实很简单的,创建了我们的静态库.a文件以及usr文件夹,这里注意一定要按照GitHub上的选择“Debug-universal”的文件夹里面的文件,否则会出错,选择iphone或者模拟器的文件都不能够完整的运作。
- 新建链接文件OCHeader.h然后 我们到 build setting里面进行设置,注意路径,如果建在某个文件夹下面的,要把文件夹名称带上,xxx/xxx.h否则会报错
- 然后,我们在这个OCHeader.h设置我们要导入的一些类
#ifndef svgtest_OCHeader_h
#define svgtest_OCHeader_h
#import "SVGKit.h" //这就是我要添加的SVGKit的类,方便我的swift直接调用
#import "SVGKImage.h" //同上
#endif
- 一次添加全局的swift都可以直接使用,
然后我在我的ViewControler中写我们的代码把
我先设置了一个button让其点击后加载我的svg格式的文件,svg格式的文件事先导入到了我的项目。
import UIKit
//cnblog里面没有swift 将就一下用了c的模板 代码里面对比了oc的例子指导代码,我们可以看到很多不同点。
class ViewController: UIViewController {
@IBOutlet var firstview: UIView!
@IBAction func showsvgbuttonclic(sender: AnyObject) {
var svgim:SVGKImage=SVGKImage(named: "Rsimplified.svg")
//SVGKImage* newImage = [SVGKImage imageNamed:@"myImage.svg"];
var svgimview=SVGKLayeredImageView(SVGKImage: svgim)
//SVGKImageView* imageView = [[SVGKLayeredImageView alloc] initWithImage:newImage];
firstview.addSubview(svgimview)
//[self.view addSubView: [[SVGKLayeredImageView alloc] initWithImage:newImage];
NSLog("showsvgbuttonclick")
}
2.2举例
新建一个 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!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, 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, width: w, 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)
}
}
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, 0, 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)
}
}