目前,SDWebImage 组织提供 3 种 SVG Coder 插件支持,以下是比较:
插件名称 | 矢量图像 | 位图图像 | 平台 | 兼容性 | 依赖 |
---|---|---|---|---|---|
SVGNativeCoder | 否 | 是 | iOS 9+ | 最佳且符合 W3C 标准 | adobe/svg-native-viewer |
SVGCoder | 是 | 是 | iOS 13+ | 可以,但在某些 SVG 上存在 Bug | Apple CoreSVG (私有) |
SVGKitPlugin | 是 | 否 | iOS 9+ | 最差,不再维护 | SVGKit/SVGKit |
SDWebImageSVGCoder 是 SDWebImage 框架的一个 SVG coder 插件,为 SVG 提供图像加载支持。
SVG 渲染使用 Apple 的 CoreSVG.framework 框架(iOS 13/macOS 10.15 中引入)。
在 1.0.0 版本之前,此 SVG Coder 由第三方库 SVGKit 提供支持。它也支持 iOS 8+ (macOS 10.10+)。
但是,由于该第三方库缺乏支持,包含大量问题且没有社区帮助,版本发布也不明确,这给我们维护带来了痛苦。因此,我们决定弃用 SVGKit 支持并将其移至另一个仓库:SDWebImageSVGKitPlugin。
使用 SVGKit 或必须支持 iOS 8+ (macOS 10.10+) 的用户仍然可以使用 SDWebImageSVGKitPlugin。您也可以同时混合使用这两种 SVG coder。但由于 Apple 已经提供了一个内置框架支持,我们更喜欢使用它,这可以减少复杂的依赖关系、代码大小,并从 Apple 的系统升级中受益。
到目前为止(Xcode 11.4 && iOS 13.4),CoreSVG.framework 仍然是私有框架。我已经发送了反馈雷达以请求公开此框架。如果可以,请帮助我们发送雷达并向 Apple 请求:https://feedbackassistant.apple.com/
CoreSVG.framework API 是稳定的,并且与 CoreGraphics 的 PDF API 概念相同,因此没有理由保持私有。我们已经提交了使用 CoreSVG 在 App Store 上渲染矢量图像的应用程序。
我们在此处使用的所有 SPI 访问都使用运行时访问和早期检查,即使未来的操作系统升级破坏了该功能,此框架也不会使您的应用程序崩溃,只会加载失败。我将持续更新,以适应每个固件更新的最新变化。
如果您仍然担心 SPI 的使用,可以使用 SDWebImageSVGKitPlugin。但我们可能不会响应与 SVGKit 相关的任何解析器或渲染问题,因为它已经不再维护。
还有另一种解决方案:SVG-Native,这是 Adobe 的一项新的 W3C 标准,它是 SVG/1.1 的一个子集。Apple/Google/Microsoft 已经加入对该标准的协议,您可以尝试使用来自 SVG-native-viewer 的代码编写自己的 coder,并为矢量图像采用 SVG-native。
警告:一些用户报告说,Apple 的 CoreSVG 在某些 SVG 上存在兼容性问题(例如使用非系统字体、渐变),从 v1.7.0 开始,我们保护了一些情况,但其他异常情况是无法捕获的。对于这些崩溃,要么使用
将 SVG 渲染为位图图像
(见下文),要么编辑您的 SVG 源文件以使 Apple 的 CoeSVG 兼容。
要运行示例项目,请克隆该存储库,并首先从 Example 目录运行pod install
。
您可以修改代码或使用一些其他 SVG 文件来检查兼容性。
SDWebImageSVGCoder 可通过 CocoaPods 获得。 要安装它,只需将以下行添加到您的 Podfile 中
pod 'SDWebImageSVGCoder'
SDWebImageSVGCoder 可通过 Carthage 获得。
github "SDWebImage/SDWebImageSVGCoder"
SDWebImageSVGCoder 可通过 Swift Package Manager 获得。
let package = Package(
dependencies: [
.package(url: "https://github.com/SDWebImage/SDWebImageSVGCoder.git", from: "1.4.0")
]
)
要使用 SVG coder,您应首先将 SDImageSVGCoder
添加到 coders 管理器。 然后,您可以调用 View Category 方法来开始加载 SVG 图像。 有关这些步骤,请参见此处的 Wiki - Coder Usage。
请注意,SVG 是一种 矢量图像 格式,并且 UIImageView/NSImageView 也支持渲染矢量图像。 这意味着您可以更改大小而不会丢失任何细节。
// register coder, on AppDelegate
SDImageSVGCoder *SVGCoder = [SDImageSVGCoder sharedCoder];
[[SDImageCodersManager sharedManager] addCoder:SVGCoder];
// load SVG url
UIImageView *imageView;
[imageView sd_setImageWithURL:url]
// Changing size
CGRect rect = imageView.frame;
rect.size.width = 200;
rect.size.height = 200;
imageView.frame = rect;
// register coder, on AppDelegate
let SVGCoder = SDImageSVGCoder.shared
SDImageCodersManager.shared.addCoder(SVGCoder)
// load SVG url
let imageView: UIImageView
imageView.sd_setImage(with: url)
// Changing size
var rect = imageView.frame
rect.size.width = 200
rect.size.height = 200
imageView.frame = rect
请注意,由于 UIImageView/NSImageView 支持这种矢量渲染,因此这意味着此 coder 插件可以与 SwiftUI 兼容。 有关用法,请检查 SDWebImageSwiftUI。
注意:对于 watchOS,它不支持 UIKit,因此您不能使用矢量图像格式。(包括 SVG 和 PDF)
在大多数情况下,矢量 SVG 是首选。 但是,有时您可能需要 SVG 的位图形式,用于图像处理或 watchOS。
默认情况下,它使用 SVG viewBox 大小。您还可以使用 .imageThumbnailPixelSize
上下文选项在图像加载期间指定所需的大小。您可以使用 .imagePreserveAspectRatio
上下文选项指定缩放期间是否保持纵横比。
注意:使用 imageThumbnailPixelSize
时,传递 0 作为宽度或高度将删除此长度的限制。例如,给定一个原始大小为 (40,50)
的 SVG 图像
保持纵横比 | 宽度 | 高度 | 效果 |
---|---|---|---|
是 | 50 | 50 | (40,50) |
是 | 0 | 100 | (80,100) |
是 | 20 | 0 | (20,25) |
是 | 0 | 0 | (40,50) |
否 | 50 | 50 | (50,50) |
否 | 0 | 100 | (40,100) |
否 | 20 | 0 | (20,50) |
否 | 0 | 0 | (40,50) |
注意:一旦您传递了 imageThumbnailPixelSize
,我们将始终生成位图表示形式。 如果您确实需要矢量格式,请不要传递它们,让 UIImageView
动态拉伸 SVG。
UIImageView *imageView;
CGSize bitmapSize = CGSizeMake(500, 500);
[imageView sd_setImageWithURL:url placeholderImage:nil options:0 context:@{SDWebImageContextThumbnailPixelSize: @(bitmapSize)];
let imageView: UIImageView
let bitmapSize = CGSize(width: 500, height: 500)
imageView.sd_setImage(with: url, placeholderImage: nil, options: [], context: [.imageThumbnailPixelSize : bitmapSize])
SDWebImageSVGCoder
提供了一种简单的方法来将此 coder 插件生成的 SVG 图像导出到原始 SVG 数据。
注意:SVG 的位图形式不支持 SVG 数据导出。
UIImage *svgImage; // UIImage with vector image, or NSImage contains `NSSVGImageRep`
if (svgImage.sd_isVector) { // This API available in SDWebImage 5.6.0
NSData *svgData = [svgImage sd_imageDataAsFormat:SDImageFormatSVG];
}
let svgImage: UIImage // UIImage with vector image, or NSImage contains `NSSVGImageRep`
if svgImage.sd_isVector { // This API available in SDWebImage 5.6.0
let svgData = svgImage.sd_imageData(as: .SVG)
}
<path d="M399.8,68.2c77.3,3.1,160.6,32.1" opacity="0.15" fill="rgb(29,36,60)" />
应用程序崩溃。
rgba
设置不透明度。<path d="M399.8,68.2c77.3,3.1,160.6,32.1" fill="rgba(29,36,60,0.15)" />
此框架支持在 iOS 12-/macOS 10.14- 上的向后兼容。 并且您可以将 SDWebImageSVGCoder
用于更高的固件版本,将 SDWebImageSVGKitPlugin
用于更低的固件版本。
对于 CocoaPods 用户,您可以使用以下方法跳过 Podfile 中的平台版本验证
platform :ios, '13.0' # This does not effect your App Target's deployment target version, just a hint for CocoaPods
请注意,您应始终使用运行时版本检查来确保这些符号可用,您还应使用 API_AVAILABLE
注释标记所有使用公共 API 的类。 见下文
if (@available(iOS 13, *)) {
[SDImageCodersManager.sharedCoder addCoder:SDImageSVGCoder.sharedCoder];
} else {
[SDImageCodersManager.sharedCoder addCoder:SDImageSVGKCoder.sharedCoder];
}
这些 SVG 图像来自 wikimedia,您也可以使用自己的 SVG 图像尝试该演示。
DreamPiggy
SDWebImageSVGCoder 在 MIT 许可下可用。 有关更多信息,请参见 LICENSE 文件。