矢量图像如何在 Xcode(即 pdf 文件)中工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25818845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do vector images work in Xcode (i.e. pdf files)?
提问by Senseful
How does vector support work in Xcode 6?
矢量支持如何在 Xcode 6 中工作?
When I try resizing an image, it looks jagged, what gives?
当我尝试调整图像大小时,它看起来是锯齿状的,这是怎么回事?
回答by Senseful
How to use vectors in Xcode (7 and 6.3+):
如何在 Xcode(7 和 6.3+)中使用向量:
- Save an image as a .pdffile at the proper @1x size (e.g. 24x24 for a toolbar button).
- In your Images.xcassetsfile, create a new Image Set.
- In the Attributes Inspector, set the Scale Factorsto Single Vector.
- Drag and drop your pdf file into the All, Universalsection.
You can now refer to your image by its name, just as you would any .pngfile.
UIImage(named: "myImage")
- 以适当的@1x 大小(例如,工具栏按钮为 24x24)将图像另存为.pdf文件。
- 在您的Images.xcassets文件中,创建一个新的Image Set。
- 在Attributes Inspector 中,将Scale Factors设置为Single Vector。
- 将您的 pdf 文件拖放到“全部”、“通用”部分。
您现在可以通过名称引用您的图像,就像使用任何.png文件一样。
UIImage(named: "myImage")
How to use vectors in older versions of Xcode (6.0 - 6.2):
如何在旧版本的 Xcode (6.0 - 6.2) 中使用向量:
- Follow the steps above, except for step 3, set Typesto Vectors.
- 按照上面的步骤,除了第 3 步,将Types设置为Vectors。
How vectors work in Xcode
向量如何在 Xcode 中工作
Vector support is confusing in Xcode, because when most people think of vectors, they think of images that can scale up and down and still look good. However, Xcode 6 and 7 don't have full vector support for iOS, so things work a little differently.
Xcode 中的矢量支持令人困惑,因为当大多数人想到矢量时,他们会想到可以放大和缩小但仍然看起来不错的图像。但是,Xcode 6 和 7 没有对 iOS 的完整矢量支持,因此工作方式略有不同。
The vector system is really simple. It takes your .pdf
image, and creates @1x.png
, @2x.png
, and @3x.png
assets at build time. (You can use a tool to examine the contents of Assets.carto verify this.)
矢量系统非常简单。这需要你的.pdf
形象,并创建@1x.png
,@2x.png
以及@3x.png
资产在构建时。(您可以使用工具检查 Assets.car 的内容来验证这一点。)
For example, assume you are given foo.pdf
which is a 44x44 vector asset. At build timeit will generate the following files:
例如,假设您得到的foo.pdf
是一个 44x44 的矢量资产。在构建时,它将生成以下文件:
[email protected]
at 44x44[email protected]
at 88x88[email protected]
at 132x132
[email protected]
在 44x44[email protected]
88x88[email protected]
132x132
This works the same for any sized image. For example, if you have bar.pdf
which is 100x100, you will get:
这对于任何大小的图像都是一样的。例如,如果你有bar.pdf
100x100,你会得到:
[email protected]
at 100x100[email protected]
at 200x200[email protected]
at 300x300
[email protected]
100x100[email protected]
200x200[email protected]
300x300
Implications:
含义:
- You cannot choose a new size for the image; it will only look good if you keep it at the 44x44 size. The reason is that full vector support is not implemented. The only thing these vectors do is save you the time of saving your image assets. If you have a tool (e.g. a Photoshop script) that already makes this a one-step process, the only thing you will gain by using pdf vectors is future-proof support(e.g. if in iOS 9 Apple begins to require @4x assets, these will just work), and you will have fewer files to maintain.
- You should ask for all your assets at the @1x size, saved as PDF files. Among other things, this will allow UIImageViews to have the correct intrinsic content size.
- 您不能为图像选择新尺寸;如果您将其保持在 44x44 尺寸,它只会看起来不错。原因是没有实现完整的向量支持。这些矢量唯一能做的就是节省您保存图像资产的时间。如果您有一个工具(例如 Photoshop 脚本)已经使此过程成为一个步骤,那么使用 pdf 向量唯一获得的是面向未来的支持(例如,如果在 iOS 9 中 Apple 开始需要 @4x 资产,这些只会起作用),并且您需要维护的文件更少。
- 您应该要求以@1x 大小保存所有资产,并保存为 PDF 文件。除此之外,这将允许 UIImageViews 具有正确的内在内容大小。
Why it (probably) works this way:
为什么它(可能)以这种方式工作:
- This makes it backwards compatiblewith previous iOS versions.
- Resizing vectors may be a computational intensive task at runtime; by implementing it this way, there are no performance hits.
- 这使得它向后兼容以前的 iOS 版本。
- 在运行时调整向量大小可能是一项计算密集型任务;通过这种方式实现它,没有性能下降。
回答by Maria
回答by Suragch
This is a supplement to the excellent answer by @Senseful.
这是对@Senseful 出色回答的补充。
How to make vector images in .pdf format
如何制作 .pdf 格式的矢量图像
I will tell how to do this in Inkscape since it is free and open source but other programs should be similar.
我将告诉如何在 Inkscape 中执行此操作,因为它是免费和开源的,但其他程序应该类似。
In Inkscape:
在 Inkscape 中:
- Create a new project.
- Go to File > Document Properties and set the custom page size to whatever your @1x size is (44x44, 100x100, etc) with the units in px.
- Make your artwork.
- Go to File > Save As... > Printable Document Format (*.pdf) > Save > OK. (Alternatively, you could go to Print > Print to File > Output format: PDF > Print but there are not as many options.)
- 创建一个新项目。
- 转到文件 > 文档属性并将自定义页面大小设置为您的@1x 大小(44x44、100x100 等),单位为 px。
- 制作您的艺术品。
- 转到文件 > 另存为... > 可打印文档格式 (*.pdf) > 保存 > 确定。(或者,您可以转到“打印”>“打印到文件”>“输出格式:PDF”>“打印”,但选项不多。)
Notes:
笔记:
- As is mentioned in the accepted answer, you cannot resize your image because Xcode still produces the rasterized images at build time. If you need to resize your image you should make a new .pdf file with a different size.
If you already have an .svg image that is the wrong page size, do the following:
- Change the page size (Inkscape > File > Document Properties)
- Select all objects (Ctrl+A) on the work space and resize them to fit in the new page size. (Hold down Ctrl to keep aspect size.)
To convert an .svg file into a .pdf you can also find online utilities to do the job for you. Here is one examplefrom this answer. This has the benefit of allowing you to set the .pdf size easily.
- 正如接受的答案中所述,您无法调整图像大小,因为 Xcode 在构建时仍会生成光栅化图像。如果您需要调整图像大小,您应该制作一个不同大小的新 .pdf 文件。
如果您已经有一个页面大小错误的 .svg 图像,请执行以下操作:
- 更改页面大小(Inkscape > 文件 > 文档属性)
- 选择工作区上的所有对象 (Ctrl+A) 并调整它们的大小以适应新的页面大小。(按住 Ctrl 以保持纵横比大小。)
要将 .svg 文件转换为 .pdf,您还可以找到在线实用程序来为您完成这项工作。下面是一个例子,从这个答案。这样做的好处是让您可以轻松设置 .pdf 大小。
Further reading
进一步阅读
回答by Dren
For those who still not updated, there were changes in Xcode 9 (iOS 11).
对于那些仍未更新的人,Xcode 9 (iOS 11) 中发生了变化。
What's new in Cocoa Touch (WWDC 2017 Session 201) (@32:55) https://developer.apple.com/videos/play/wwdc2017/201/
Cocoa Touch 的新增功能(WWDC 2017 Session 201)(@32:55) https://developer.apple.com/videos/play/wwdc2017/201/
In few words, Asset Catalog now includes the new checkbox in Attributes Inspector named “Preserve Vector Data”. When checked, PDF data will be included in the compiled binary, increasing its size of course. But it gives a chance for iOS to scale the vector data in both directions and provide nice images.(With its own difficulties). For iOS below 11, old scaling mechanisms described in answers upwards is used.
简而言之,资产目录现在包括属性检查器中名为“保留矢量数据”的新复选框。选中时,PDF 数据将包含在编译的二进制文件中,当然会增加其大小。但它让 iOS 有机会在两个方向上缩放矢量数据并提供漂亮的图像。(有其自身的困难)。对于低于 11 的 iOS,使用上面的答案中描述的旧缩放机制。
回答by Bruno Paulino
You can use normal PDF files inside your project as Vector images and render images of any size using this extension. This way is way better because iOS will not generate .PNG images out of your PDF files, plus you can render you images with any size you want:
您可以将项目中的普通 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
}
}
}