为什么在 SwiftUI 中调整 PDF 的大小会变得锐利? [英] Why do PDFs resized in SwiftUI getting sharp edges?
问题描述
我尝试使用 Xcode 11.4 和 iOS 13.4 在支持 SwiftUI 的应用程序中包含 pdf.但是,当我调整 pdf 大小时,它的边缘会变得粗糙.我包含了 pdf 的两个版本:一个大 pdf (icon.pdf
) 和一个小 pdf (icon_small.pdf
).当我调整 icon.pdf
的大小时,它会获得起始边缘,而 icon_small.pdf
会获得平滑的边缘.该问题也适用于我尝试过的所有其他 pdf.
这是我的代码:
struct ContentView:查看{var主体:一些视图{虚拟堆栈{垫片()文本(icon.pdf:")图像(图标").resizable().renderingMode(.template).aspectRatio(contentMode: .fit).frame(宽:27.0,高:27.0)垫片()文本(icon_small.pdf:")图像(icon_small")垫片()}}}
icon.pdf
和 icon_small.pdf
都有以下资产设置:
- 渲染为:模板图像
- 调整大小:保留矢量数据
- 设备:通用
- 量表:单量表
可在此处获得 pdf:
- <小时><小时><小时>
I try to include a pdf in my SwiftUI enabled app using Xcode 11.4 and iOS 13.4. However, when I resize the pdf, it gets crips edges. I have included two versions of the pdf: One large pdf (
icon.pdf
) and one small pdf (icon_small.pdf
). When I resizeicon.pdf
it gets start edges, whileicon_small.pdf
gets smooth edges. The issue applies to all other pdfs I have tried as well.This is my code:
struct ContentView: View { var body: some View { VStack { Spacer() Text("icon.pdf:") Image("icon") .resizable() .renderingMode(.template) .aspectRatio(contentMode: .fit) .frame(width: 27.0, height: 27.0) Spacer() Text("icon_small.pdf:") Image("icon_small") Spacer() } } }
Both
icon.pdf
andicon_small.pdf
have the following asset settings:- Render As: Template Image
- Resizing: Preserve Vector Data
- Devices: Universal
- Scales: Single Scale
The pdfs are available here:
- http://simensolbakken.com/public/stackoverflow/icon.pdf
- http://simensolbakken.com/public/stackoverflow/icon_small.pdf
解决方案I did a side by side comparison for both vector images using the ones you provided:
At first, I used
SwiftUI
's inbuiltImage
and as mentioned, both performed badly at their extreme ends:- Large image got sharp edges when it scaled down
- Small image got blurred as it scaled up
At first I thought it might be your pdf vectors so I used ones that I know have worked well in my previous projects, but I got the same issues.
Thinking it to be aUIImage
issue, I usedSwiftUI
sImage(uiImage:)
but same problem.Last guess was the image container, and knowing that
UIImageView
has handled vector images well, gettingUIViewRepresentable
to wrap theUIImageView
seems to solve this issue. And for now it looks like a possible workaround.Workaround Solution:
struct MyImageView: UIViewRepresentable { var name: String var contentMode: UIView.ContentMode = .scaleAspectFit var tintColor: UIColor = .black func makeUIView(context: Context) -> UIImageView { let imageView = UIImageView() imageView.setContentCompressionResistancePriority(.fittingSizeLevel, for: .vertical) return imageView } func updateUIView(_ uiView: UIImageView, context: Context) { uiView.contentMode = contentMode uiView.tintColor = tintColor if let image = UIImage(named: name) { uiView.image = image } } }
This loses some
SwiftUI
Image
modifiers (you still have normalView
modifiers) but you can always pass in some parameters such ascontentMode
andtintColor
as shown above. Add more if needed and handle accordingly.
Usage Example:
struct ContentView: View { var body: some View { VStack { MyImageView(name: "icon", //REQUIRED contentMode: .scaleAspectFit, //OPTIONAL tintColor: .black /*OPTIONAL*/) .frame(width: 27, height: 27) MyImageView(name: "icon_small", //REQUIRED contentMode: .scaleAspectFit, //OPTIONAL tintColor: .black /*OPTIONAL*/) .frame(width: 27, height: 27) } } }
Now this is all speculation but it looks as though
SwiftUI
treats vector images as aPNG
.The following example is a simple side by side comparison of the small and large vector images rendered in
UIKit
'sUIImageView
andSwiftUI
'sImage
.Comparison:
struct ContentView: View { let (largeImage, smallImage) = ("icon", "icon_small") let range = stride(from: 20, to: 320, by: 40).map { CGFloat($0) } var body: some View { List(range, id: .self) { (side) in ScrollView(.horizontal) { VStack(alignment: .leading) { Text(String(format: "%gx%g", side, side)) HStack { VStack { Text("UIKit") MyImageView(name: self.smallImage) .frame(width: side, height: side) MyImageView(name: self.largeImage) .frame(width: side, height: side) } VStack { Text("SwiftUI") Image(self.smallImage) .resizable() .aspectRatio(contentMode: .fit) .frame(width: side) Image(self.largeImage) .resizable() .aspectRatio(contentMode: .fit) .frame(width: side) } } } } } } }
Results:
- Top row; Left : Small Image in
UIImageView
- Top row; Right : Small Image in
SwiftUI
Image
- Bottom row; Left : Large Image in
UIImageView
- Bottom row; Right : Large Image in
SwiftUI
Image
UIKit
'sUIImageView
has consistent performace whileSwiftUI
'sImage
is having trouble.
这篇关于为什么在 SwiftUI 中调整 PDF 的大小会变得锐利?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!