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

矢量图像如何在Xcode(即pdf文件)中工作?,xcode,vector-graphics,Xcode,Vector Graphics,矢量支持在Xcode 6中是如何工作的 当我尝试调整图像大小时,它看起来参差不齐,有什么好处?如何在Xcode(7和6.3+)中使用向量: 以适当的@1x大小(例如)将图像另存为.pdf文件 在Images.xcsets文件中,创建一个新的图像集 在属性检查器中,将比例因子设置为单个向量 将pdf文件拖放到全部、通用部分 现在,您可以通过名称引用图像,就像引用任何.png文件一样 如何在旧版本的Xcode(6.0-6.2)中使用向量: 按照上述步骤进行操作,除了步骤3,将类型设置为向量

矢量支持在Xcode 6中是如何工作的

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

如何在Xcode(7和6.3+)中使用向量:
  • 以适当的@1x大小(例如)将图像另存为.pdf文件
  • 在Images.xcsets文件中,创建一个新的图像集
  • 属性检查器中,将比例因子设置为单个向量
  • 将pdf文件拖放到全部、通用部分
  • 现在,您可以通过名称引用图像,就像引用任何.png文件一样

  • 如何在旧版本的Xcode(6.0-6.2)中使用向量:
    • 按照上述步骤进行操作,除了步骤3,将类型设置为向量

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

    向量系统非常简单。它获取您的
    .pdf
    图像,并在构建时创建
    @1x.png
    @2x.png
    @3x.png
    资产。(您可以通过以下方式进行验证。)

    例如,假设您获得了一个44x44矢量资源
    foo.pdf
    。在构建时,它将生成以下文件:

    • foo@1x.png
      在44x44处
    • foo@2x.png
      在88x88处
    • foo@3x.png
      在132x132处
    这适用于任何大小的图像。例如,如果您有100x100的
    bar.pdf
    ,您将得到:

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

    启示:
    • 您不能为图像选择新的大小;只有保持44x44的尺寸才好看。原因是没有实现完全向量支持。这些向量所做的唯一一件事就是节省您保存图像资源的时间。如果您有一个工具(例如Photoshop脚本)已经使这成为一个一步的过程,那么使用pdf vectors您将获得的唯一好处就是经得起未来考验的支持(例如,如果在iOS 9中Apple开始需要@4x资产,那么这些就可以正常工作了),并且您需要维护的文件将更少
    • 您应该以@1x大小请求所有资产,并保存为PDF文件。除其他外,这将允许UIImageView具有正确的固有内容大小
    它(可能)以这种方式工作的原因:
    • 这使得它与以前的iOS版本向后兼容
    • 在运行时调整向量大小可能是计算密集型任务;通过这种方式实现,不会对性能造成影响

    这是对@senseve优秀答案的补充

    如何制作.pdf格式的矢量图像 我将讲述如何在Inkscape中实现这一点,因为它是免费的、开源的,但其他程序也应该类似

    在Inkscape中:

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

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

    • 更改页面大小(Inkscape>文件>文档属性)
    • 选择工作空间上的所有对象(Ctrl+A),并调整其大小以适应新的页面大小。(按住Ctrl键以保持纵横比大小。)
    • 要将.svg文件转换为.pdf文件,您还可以找到在线实用程序来完成这项工作。从…起这样做的好处是可以轻松设置.pdf大小

    进一步阅读

    您可以使用项目中的普通PDF文件作为矢量图像,并使用此扩展渲染任何大小的图像。这种方式更好,因为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
            }
        }
    
    }
    

    在Xcode 8中,您仍然可以添加pdf,创建新的图像集,并在属性检查器中,将比例设置为单比例选项。

    对于那些仍然没有更新的用户,Xcode 9(iOS 11)中有一些变化

    Cocoa Touch的新功能(WWDC 2017年第201期)(@32:55)

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

    写得不错。这将在2014年WWDC第411次会议-“Interface Builder中的新功能”44:13讨论。注意,他们说光栅化是在构建时完成的。同样有趣的是,在MAC上,它将在运行时使用向量。在未来的某个遥远的时刻,希望iOS也会这样做。不幸的是,它没有缩放切片值。因此,如果您在5处剪切角点,则无法将2x和3x图像的角点缩放为10和15。@Jesse如果您要缩放切片值,可以自行缩放
        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
            }
        }
    
    }