SVGgh 一个适用于 iOS 的 SVG 渲染框架
作者 Glenn R. Howes,所有者 Generally Helpful Software
关于未来的注意
到目前为止(2021年),我强烈建议查看 SFSymbols 的使用,因为在过去我常常使用 SVGgh。尽管如此,SVG 的制作比完整权重的 SFSymbol 简单一些。
简介
在我自己的应用中,我常常希望避免在界面元素中使用位图图像。我经常需要为 Retina、非 Retina iPhone 和 iPad 添加 PNG 文件,并发现自己受限于界面元素可以做什么。所有这些艺术作品使我的应用程序变得庞大。因此,我决定实施一个 SVG 渲染器,该渲染器可以使用标准的 可伸缩矢量图形 文档来绘制按钮图标、背景艺术或其他任何艺术需求。我有一些在 App Store 上的应用程序,如 SVG Paths,其中唯一的 PNG 文件是所需的图标。
功能
能够很好地处理形状,如路径、椭圆、圆、矩形、多边形、折线和弧,并包含所有标准的样式属性。实现基本的文字和字体处理,包括沿着路径的粗体文字。实现线性梯度和对径向梯度的支持,包括应用梯度到线条和文字。实现可伸缩的线条宽度。提供静态UIView子类、UIControl按钮和分段控件。所有这些都是可配置的,可以通过nib或storyboards设置。支持嵌入标准格式的位图图像。
可以导出为PDF,创建UIImages,并通过UIPrintInteractionController机制打印。
可以集成到SwiftUI视图中。请参阅调试应用程序中的卡片示例。
在Xcode调试器中,你可以使用快速查看按钮(即眼睛图标)来查看SVGRenderer的内容。
限制
没有实现整个SVG规范。目前,它只实现了我需要的或可能需要的规范部分。特别是,它不支持SVG字体、动画、JavaScript、CSS或效果。此外,一些属性尚未实现或部分实现,例如,无法将Svg实体的宽度属性表示为百分比。我希望此库的使用者至少能贡献一些这些的实现。
无疑存在错误,但我已在App Store中所有的8个应用程序中使用了此库而没有任何问题,所以它相对稳定。此外,尽管我的使用方式中没有理由抱怨它的性能,但我不会将其标记为一个高性能渲染器。
包含的库假设了ARC风格的内存管理。同时,它被设置为支持iOS 9及以上版本。我已转向使用代码注释,例如nullable,因此需要Xcode的最新版本来编译。支持传统和基于模块的框架包含。
最初,这是作为静态库分发的,但现在已经不是使用它的现代方式了。因此,包含的项目将构建一个框架,大多数开发者可能会发现使用CocoaPods
更令人愉快。需要CocoaPods 0.39或更高版本。
我为具有iOS 8及以上最低操作系统版本的环境启用了IB_DESIGNABLE
,这样艺术作品和小部件就可以在Interface Builder中显示出来。CocoaPods用户应该在Podfile中放置use_frameworks!
。
分段控件尚未准备用于tvOS应用程序。
作为一个黑盒库
如果您只想使用代码运行在您的应用程序中,并不关心底层的引擎,所包含的 Xcode 项目生成了一个框架(强烈推荐:SVGgh),以下是其提供的公共头文件。顺便一提,类通常带有 GH(Generally Helpful,或Glenn Howes)前缀,这并不是自恋,而是一次尝试绕过传统 Objective-C 中的命名空间缺失。
- SVGDocumentView.h 一个简单的 UIView,可用于显示 SVG 文档
- GHButton.h 一个灵活的 UIControl,可将嵌入的 SVG 文档作为图标
- GHSegmentedControl.h 一个初步控制,模仿 UISegmentedControl(不完整)
- SVGParser.h 一个用于加载 .svg 文件的类
- SVGRenderer.h 一个将 SVG 文档渲染到 CGContextRef 的类
- GHControlFactory.h 一个单例类,致力于成为小部件主题外观的中心位置
- GHImageCache.h 一个单例类,致力于缓存和加载位图图像
- SVGToPDFConverter.h 一个将渲染内容转换为 PDF 的类
- SVGPrinter.h 一个将渲染内容发送到打印机的类
如果您熟悉使用 CocoaPods 并将其用于您的项目
-
在您的 PodFile 中插入
pod 'SVGgh'
• 如果您将部署目标设置为 iOS 8 或更高版本,您应该在 Podfile 中插入use_frameworks!
。 -
通过 CocoaPods 执行更新您的 Xcode 工作空间的常规程序。如
pod update
、pod install
等。
如果您熟悉使用 Carthage 并将其用于您的项目
- 将 GenerallyHelpfulSoftware/SVGgh 添加到您的 Cartfile
- 执行
carthage update
命令 - 将框架拖到您自己的 Xcode 项目中
有关更多信息,请访问 https://github.com/Carthage/Carthage
如果您不使用 CocoaPods
要编译框架。
- 在 Xcode 6.3 或以上版本中加载所包含的 SVGgh.xcodeproj 项目
- 构建 Framework 目标。
- 找到 SVGgh.framework 框架
- 将框架拖到您自己的 Xcode 项目中
要使用,请按照以下步骤操作
- 将 SVGgh 库添加到您的 Xcode 项目中。
#include <SVGgh/SVGgh.h>;
安装库之后
- 在您的应用程序启动初期,调用 [GHControlFactory setDefaultScheme:kColorSchemeClear];
- 在您的应用程序启动初期,调用 MakeSureSVGghLinks(); 以便仅链接在故事板或nib中引用的类。例如:
# import <SVGgh/SVGgh.h>
@implementation YourAppDelegate
+(void) initialize
{
[super initialize];
MakeSureSVGghLinks(); // classes only used in Storyboards might not link otherwise
[GHControlFactory setDefaultScheme:kColorSchemeClear];
[GHControlFactory setDefaultTextColor:[UIColor greenColor]];
}
...
- 如果您使用Swift编程而不在Podfile中使用
use_frameworks!
选项,您需要在桥接头文件中添加#import <SVGgh/SVGgh.h>
。如果您使用use_frameworks!
,则应在引用SVGgh类的文件中使用import SVGgh
。在您的App委托中,您可能想在早期的地方放置初始化代码,比如:
import SVGgh
override class func initialize()
{
super.initialize()
MakeSureSVGghLinks()
let tintColor = UIColorFromSVGColorString("#5D6")!
GHControlFactory.setDefaultButtonTint(tintColor)
}
要向.xib文件或故事板中添加按钮
- 将UIView拖到您的视图中
- 在 身份检查器 中,将其 自定义类 命名为 GHButton
- 在Xcode中,您应该在属性检查器窗格中看到以下自定义属性
键路径 | 类型 | 值 |
---|---|---|
艺术品路径 | 字符串 | 艺术品/菜单按钮(假定您有这类资产) |
方案编号 | 数字 | 3 |
- 注意,假定扩展名为.svg
- 或者如果您正在制作文本按钮
键路径 | 类型 | 值 |
---|---|---|
标题 | 本地化字符串 | 我的标签 |
方案编号 | 数字 | 3 |
- 以下是一个可用的颜色方案列表,其中一些比其他更有用。我更喜欢3,kColorSchemeClear。
常量 | 枚举 | 描述 |
---|---|---|
0 | kColorSchemeiOS | 圆形实心按钮,带细边环 |
1 | kColorSchemeMachine | 从上到下的灰色渐变,带边环 |
2 | kColorSchemeKeyboard | 灰色渐变,顶部较亮,无边环 |
3 | kColorSchemeClear | 灰色渐变,顶部较亮,带边环 |
4 | kColorSchemeEmpty | 没有铬。只是艺术品或标签 |
5 | kColorSchemeHomeTheatre | 刺眼的金色渐变,带边环 |
6 | kColorSchemeiOSVersionAppropriate | kColorSchemeEmpty在iOS上,kColorSchemeTVOS在AppleTV上 |
7 | kColorSchemeFlatAndBoxy | 实心填充颜色,带方形角落。 |
8 | kColorSchemeTVOS | 尝试模仿AppleTV按钮的外观和行为。 |
- SVG文档有一个属性名为
currentColor
。您可以通过访问UIControl的textColor
、textColorPressed
和textColorSelected
属性来更改按钮按下时的外观。您可以从故事板访问它们,或者可以在初始化方法中全局设置。您的SVG必须使用currentColor而不是某些显式颜色。
要将静态视图添加到.xib文件或故事板
- 将UIView拖到您的视图中
- 在 身份检查器 中,将其 自定义类 命名为 SVGDocumentView
- 使用Xcode 6或更高版本,您应该在属性检查器窗格中看到以下自定义属性
键路径 | 类型 | 值 |
---|---|---|
艺术品路径 | 字符串 | 艺术品/我的背景 |
-
注意,假定扩展名为.svg。如果需要,您可以指定一个自定义文件扩展名。例如,如果您正在使用
.svgz
文件,您需要在Artwork Path
中包含文件扩展名。 -
您可能会打开 **属性检查器** 选项卡,并将 **模式** 设置为 **Aspect Fit** 或可能为 **Aspect Fill**。
-
如果您仅针对iOS 9及以上进行部署且想使用XCAsset类型的资源,您可以在应用程序委托的初始化方法中添加以下内容
SVGghLoaderManager.setLoaderToType(SVGghLoaderTypeDataXCAsset)
- 如果您想自定义加载SVG文档,您可以通过以下方式安装自定义加载器:
SVGghLoaderManager.setLoader(myCustomLoaderInstance)
提示
- 我喜欢把我目标添加为“文件夹引用”的“艺术品文件夹”加入其中,这样我就可以直接从Finder中拖入,它们就会被添加。文件夹引用在Xcode中显示为蓝色文件夹。
- SVG具有本地化内容的特性,如下面的片段可以本地化为中文:
<switch>
<g systemLanguage ="zh">
<text x="24" y="20" font-family="Helvetica" font-size="22" fill="grey">绝对直线</text>
<text x="218" y="95" font-family="Helvetica" font-style="italic" font-size="20" text-anchor="end" fill="blue">终点 x, y</text>
</g>
<g>
<text x="24" y="20" font-family="Helvetica" font-size="22" fill="grey">line to</text>
<text x="218" y="95" font-family="Helvetica" font-style="italic" font-size="20" text-anchor="end" fill="blue">end x, y</text>
</g>
</switch>
- 我已经提供了一份Example.xcodeproj,它在一个视图中显示SVG,并显示了一个分享按钮。
内部细节
如果您倾向于修复错误或添加功能,请尽管这么做,您将对我们将SVG文档转换为屏幕上的图像的通用机制感兴趣。
起点是SVGRenderer
,它是SVGParser
的子类,能够加载SVG文档的XML并用于在Core Graphics上下文(一个CGContextRef)中渲染。解析器将XML转换为由NSDictionaries和NSDictionaries组成的数组形成的树。这个树的根部的NSDictionary用于创建一个GHShapeGroup
,该组启动创建由SVGAttributedObject
组成的树的流程,其中每个对象都知道如何渲染自己。通常,当向SVGAttributedObject发送消息时,会提供一个实现SVGContext
协议的对象,以便SVGAttributedObject可以访问某些状态信息,例如当前颜色或查找记录树中的方法,无论是命名对象还是由父对象定义的属性。
我已经在所有头文件中添加了Doxygen风格的注释,因此有可能找到您的路线。
归属
尽管这个版本中的大多数代码都是我亲自编写的。但有几个类或类别是在网上找到的,它们的许可证足够灵活,可以包括在这里。
- [Ryan Hornberger] (http://www.ryanhornberger.com) 足够周到,做了一件事,那就是创建了一个库的CocoaPod Spec,使这个库更加有用。
- 虽然自那时起已经增长了很多,但我认为我的UIColorFromSVGColorString库基础的代码来自[Erica Sadun] (https://github.com/erica)。