矢量图像如何在Xcode(即pdf文件)中工作?


179

向量支持在Xcode 6中如何工作?

当我尝试调整图像大小时,它看起来参差不齐,这有什么用?

Answers:


356

如何在Xcode(7和6.3+)中使用向量:

  1. 以适当的@ 1x大小将图像另存为.pdf文件(例如,工具栏按钮为24x24)。
  2. 在您的Images.xcassets文件中,创建一个新的Image Set
  3. 在“属性”检查器中,将比例因子设置为“单个矢量”
  4. 将pdf文件拖放到“所有通用”部分。
  5. 现在,您可以通过图像名称来引用图像,就像处理任何.png文件一样。

    UIImage(named: "myImage")
    

如何在旧版Xcode(6.0-6.2)中使用向量:

  • 请按照上述步骤操作,但步骤3除外,将类型设置为Vectors

向量在Xcode中的工作方式

在Xcode中,向量支持令人困惑,因为当大多数人想到向量时,他们就会想到可以放大和缩小并仍然看起来不错的图像。但是,Xcode 6和7没有对iOS的完整矢量支持,因此工作原理有所不同。

向量系统非常简单。这需要你的.pdf形象,并创建@1x.png@2x.png以及@3x.png资产在构建时。(您可以使用工具检查Assets.car的内容以进行验证。)

例如,假设您给出foo.pdf了44x44矢量资产。在构建时,它将生成以下文件:

  • foo@1x.png 在44x44
  • foo@2x.png 在88x88
  • foo@3x.png 在132x132

这对于任何大小的图像都相同。例如,如果您具有bar.pdf100x100,则将获得:

  • bar@1x.png 在100x100
  • bar@2x.png 在200x200
  • bar@3x.png 在300x300

含义:

  • 您不能为图像选择新的尺寸;如果您将其保持在44x44尺寸,它只会看起来不错。原因是没有实现完整的向量支持。这些向量唯一要做的就是节省您保存图像资产的时间。如果您已经有一个工具(例如Photoshop脚本)已经使它成为一个步骤,那么使用pdf矢量唯一可以获得的就是对未来的支持(例如,如果在iOS 9中,Apple开始要求使用@ 4x资产,这些都可以使用),并且您需要维护的文件更少
  • 您应该以@ 1x大小要求所有资产,另存为PDF文件。除其他外,这将允许UIImageViews具有正确的固有内容大小。

为什么(可能)以这种方式工作:

  • 这使其与以前的iOS版本向后兼容
  • 调整向量的大小可能是运行时的计算密集型任务。通过这种方式实施,不会对性能造成影响

8
很好写。2014年WWDC会话411-“ Interface Builder的新增功能”在时间44:13中对此进行了讨论。请注意,他们说栅格化是在构建时完成的。同样有趣的是,在MAC上它将在运行时使用向量。希望在将来的某个时候,iOS也会出现。
Mike Vosseller 2014年

16
不幸的是,它不会缩放切片值。因此,如果您在5处切角,则对于2x和3x图像不会将其缩放到10和15。
杰西2014年

5
@Jesse如果您想缩放切片值,则可以在代码中自己使用,resizableImageWithCapInsets:并将切片值除以[UIScreen mainScreen].scale
Arie Litovsky,2014年

1
要澄清@ArieLitovsky关于切片的建议:您应该从资产中删除切片并将其移到代码中,例如CGFloat scale = [UIScreen mainScreen].scale; UIImage *image = [[UIImage imageNamed:@"my_unsliced_asset"] resizableImageWithCapInsets:UIEdgeInsetsMake(10 * scale, 11 * scale, 12 * scale, 13 * scale)];
glyuck 2014年

6
如何针对XCode 8执行此操作?该选项似乎已消失!
杰拉尔德

27

在Xcode 8中,您仍然可以添加pdf,创建新的图像集,并在“属性”检查器中将“缩放比例设置为单一比例”选项。 在此处输入图片说明


16

这是@Senseful出色回答的补充。

如何制作.pdf格式的矢量图像

我将告诉您如何在Inkscape中执行此操作,因为它是免费的开放源代码,但其他程序也应该类似。

在Inkscape中:

  1. 创建一个新项目。
  2. 转到“文件”>“文档属性”,然后将自定义页面大小设置为@ 1x大小(44x44、100x100等),单位为px。
  3. 制作艺术品。
  4. 转到文件>另存为...>可打印文档格式(* .pdf)>保存>确定。(或者,您可以转到打印>打印到文件>输出格式:PDF>打印,但是没有那么多的选项。)

笔记:

  • 如已接受的答案中所述,您无法调整图像大小,因为Xcode在生成时仍会生成栅格化图像。如果需要调整图像大小,则应制作一个具有不同大小的新.pdf文件。
  • 如果您已经具有错误的页面大小的.svg图像,请执行以下操作:

    1. 更改页面大小(Inkscape>文件>文档属性)
    2. 选择工作空间上的所有对象(Ctrl + A),然后调整它们的大小以适合新的页面大小。(按住Ctrl键可保持外观尺寸不变。)
  • 要将.svg文件转换为.pdf,您还可以找到在线实用程序来为您完成这项工作。下面是一个例子,从这个答案。这样的好处是允许您轻松设置.pdf大小。

进一步阅读


14

对于仍未更新的用户,Xcode 9(iOS 11)有所更改。

Cocoa Touch(WWDC 2017 Session 201)(@ 32:55)的新功能 https://developer.apple.com/videos/play/wwdc2017/201/

简而言之,资产目录现在在属性检查器中包括名为“保留矢量数据”的新复选框。选中后,PDF数据将包含在已编译的二进制文件中,当然会增加其大小。但这为iOS提供了在两个方向上缩放矢量数据并提供精美图像的机会(有其自身的困难)。对于11以下的iOS,使用向上答案中描述的旧缩放机制。


1

您可以在项目内部将普通PDF文件用作Vector图像,并使用此扩展名呈现任意大小的图像。这种方式更好,因为iOS不会从您的PDF文件中生成.PNG图像,此外,您还可以使用任意大小的图像进行渲染:

    extension UIImage {

    static func fromPDF(filename: String, size: CGSize) -> UIImage? {
        guard let path = Bundle.main.path(forResource: filename, ofType: "pdf") else { return nil }
        let url = URL(fileURLWithPath: path)
        guard let document = CGPDFDocument(url as CFURL) else { return nil }
        guard let page = document.page(at: 1) else { return nil }

        let imageRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
        if #available(iOS 10.0, *) {
            let renderer = UIGraphicsImageRenderer(size: size)
            let img = renderer.image { ctx in
                UIColor.white.withAlphaComponent(0).set()
                ctx.fill(imageRect)
                ctx.cgContext.translateBy(x: 0, y: size.height)
                ctx.cgContext.scaleBy(x: 1.0, y: -1.0)
                ctx.cgContext.concatenate(page.getDrawingTransform(.artBox, rect: imageRect, rotate: 0, preserveAspectRatio: true))
                ctx.cgContext.drawPDFPage(page);
            }

            return img
        } else {
            // Fallback on earlier versions
            UIGraphicsBeginImageContextWithOptions(size, false, 2.0)
            if let context = UIGraphicsGetCurrentContext() {
                context.interpolationQuality = .high
                context.setAllowsAntialiasing(true)
                context.setShouldAntialias(true)
                context.setFillColor(red: 1, green: 1, blue: 1, alpha: 0)
                context.fill(imageRect)
                context.saveGState()
                context.translateBy(x: 0.0, y: size.height)
                context.scaleBy(x: 1.0, y: -1.0)
                context.concatenate(page.getDrawingTransform(.cropBox, rect: imageRect, rotate: 0, preserveAspectRatio: true))
                context.drawPDFPage(page)
                let image = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return image
            }
            return nil
        }
    }

}

1
我尝试了此方法,但似乎无法将图像缩放到更大的像素大小?我得到的UIImage本身是正确的大小;只是矢量图像居中且仍保持PDF的原始像素大小。(我想将其缩放到UIImage的大小。)您知道这是否可能吗?
DivideByZer0
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.