Reputation: 211
I'm trying to use vector-based PDF images using "Single-Scale" in an app I'm working on using SwiftUI in Xcode 11, but the image always looks blurry when I scale it up in size.
I had no trouble with this in UIKit in Xcode 11. I created a dummy app with 2 scenes, both displaying the same vector image. I created the first scene in a storyboard, then used a HostingViewController to embed an identical scene made in SwiftUI. When I ran the app, the first scene (UIKit) displayed a crisp, non blurry image. The second (SwiftUI) scene however, was blurry and didn't appear to be using vector data, despite using the same source image asset.
I was able to "work around" this by creating a UIImage with the vector image, then using this UIImage extension to resize the UIImage before it's passed into Image
. However, the size I enter in the resized(to:)
method makes no difference at runtime, so I also have to add .frame(w:,h:)
to image
in 'var body' to make it show the correct size.
let uiImage = UIImage(named: "Logo-vector")!
var image: Image {
Image(uiImage: uiImage.resized(to: CGSize(width: 500, height: 500)))
.resizable()
}
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 8) {
Spacer()
Text("Logo vector SwiftUI")
image
.frame(width: 240, height: 216)
...
}
...
}
}
}
extension UIImage {
func resized(to size: CGSize) -> UIImage {
return UIGraphicsImageRenderer(size: size).image { _ in
draw(in: CGRect(origin: .zero, size: size))
}
}
}
The image is clear and properly resized at runtime with this workaround, but it feels like a bit of a hack.
I've looked everywhere online for a different solution or anyone else having this issue specifically with SwiftUI, but haven't found anything at all.
Has anyone else had this issue or does anyone have a better solution?
Upvotes: 20
Views: 6828
Reputation: 144
I put together a cross-platform framework called ResizableVector which performs the same resizing method.
extension PlatformImage {
func resized(to size: CGSize) -> PlatformImage {
return GraphicsImageRenderer(size: size).image { _ in
self.draw(in: CGRect(origin: .zero, size: size))
}
}
}
Where PlatformImage is simply a typealias for UIImage or NSImage and GraphicsImageRenderer is a typealias for the UIGraphicsImageRenderer or MacGraphicsImageRenderer.
The framework provides a SwiftUI View named ResizableVector to use in place of Image. It can also respect the original aspect ratio, if desired.
You can add this using SPM - check it out on GitHub: https://github.com/Matt54/ResizableVector
Upvotes: 1
Reputation: 49
try enabling "IPreserve Vector Data" on each pdf image asset (select image in "Assets.xcassets" folder, then in "Attributes inspector > Image Set > Resizing")
Upvotes: 4