我有一个UIScrollView
,里面有一个UIImage
,可以从服务器上获得。每个图像的width
大于height
,或者height
大于width
。
我想根据height
或width
例如:
我从服务器获取图像,然后检查哪个更大,width
或height
。
if let width = image?.size.width, let height = image?.size.height {
if width > height {
print("Width is greater than height")
}else
print("Height is greater than width")
}
}
一旦执行完此操作,我便希望以这两种方式之一缩放图像。
选项1:
如果width
大于height
,那么我希望图像相对于其height
进行缩放,并将其固定为设备的高度,宽度应为scrollable
视图。
选项2:
如果height
大于width
,那么我希望图像相对于其width
进行缩放,并将其固定为设备的宽度,高度应为scrollable
视图。
我设法使Option 2
可以使用此功能。
func scaleImageWidth(sourceImage:UIImage, scaledToWidth: CGFloat) -> UIImage {
let oldWidth = sourceImage.size.width
let scaleFactor = scaledToWidth / oldWidth
let newHeight = sourceImage.size.height * scaleFactor
let newWidth = oldWidth * scaleFactor
UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
sourceImage.draw(in: CGRect(x:0, y:0, width:newWidth, height:newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
我修改了该功能以使其适用于Option 1
,如下所示:
func scaleImageHeight(sourceImage: UIImage, scaledToHeight: CGFloat) -> UIImage {
let oldheight: CGFloat = sourceImage.size.height
let scaleFactor: CGFloat = scaledToHeight / oldheight
let newWidth: CGFloat = sourceImage.size.width * scaleFactor
let newHeight: CGFloat = oldheight * scaleFactor
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
sourceImage.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
现在这两个功能都可以正常工作,但是在两种情况下,缩放都会导致图像缩放小于设备的width
或height
。
以下是缩放错误时的外观图像。
实际结果:
预期结果:
已编辑
:以下是其中一些height
和width
这些功能正常工作的图像。
情况1:当“高度”大于“宽度”
情况2:当“宽度”大于“高度”
以下是其中一些图像,这些函数的height
和width
会产生上述问题。
情况1:当“高度”大于“宽度”
情况2:当“宽度”大于“高度”
当宽度大于高度时,我没有发现任何问题。在这种情况下,它总是会产生正确的结果。
答案 0 :(得分:1)
我认为问题可能在于您正在比较图像的宽度:高度,但没有考虑imageView的纵横比。
这里有一个CGSize
扩展名,可根据“源”大小(图像大小)和“目标”大小(imageView)来计算aspectFit
或aspectFill
大小大小)。
extension CGSize {
func aspectFit(sourceSize: CGSize, targetSize: CGSize) -> CGSize {
let vWidth = targetSize.width / sourceSize.width;
let vHeight = targetSize.height / sourceSize.height;
var returnSize = targetSize
if( vHeight < vWidth ) {
returnSize.width = targetSize.height / sourceSize.height * sourceSize.width;
}
else if( vWidth < vHeight ) {
returnSize.height = targetSize.width / sourceSize.width * sourceSize.height;
}
return returnSize;
}
func aspectFill(sourceSize: CGSize, targetSize: CGSize) -> CGSize {
let vWidth = targetSize.width / sourceSize.width;
let vHeight = targetSize.height / sourceSize.height;
var returnSize = targetSize
if( vHeight > vWidth ) {
returnSize.width = targetSize.height / sourceSize.height * sourceSize.width;
}
else if( vWidth > vHeight ) {
returnSize.height = targetSize.width / sourceSize.width * sourceSize.height;
}
return returnSize;
}
}
对于您的情况,您希望获得aspectFill
的大小。
这是一个简单的完整示例,该示例将原始计算的输出与aspectFill
计算进行比较。我使用了您添加到问题中的图像尺寸,以及375 x 667
的imageView尺寸(在iPhone 7上为全屏显示):
extension CGSize {
func aspectFit(sourceSize: CGSize, targetSize: CGSize) -> CGSize {
let vWidth = targetSize.width / sourceSize.width;
let vHeight = targetSize.height / sourceSize.height;
var returnSize = targetSize
if( vHeight < vWidth ) {
returnSize.width = targetSize.height / sourceSize.height * sourceSize.width;
}
else if( vWidth < vHeight ) {
returnSize.height = targetSize.width / sourceSize.width * sourceSize.height;
}
return returnSize;
}
func aspectFill(sourceSize: CGSize, targetSize: CGSize) -> CGSize {
let vWidth = targetSize.width / sourceSize.width;
let vHeight = targetSize.height / sourceSize.height;
var returnSize = targetSize
if( vHeight > vWidth ) {
returnSize.width = targetSize.height / sourceSize.height * sourceSize.width;
}
else if( vWidth > vHeight ) {
returnSize.height = targetSize.width / sourceSize.width * sourceSize.height;
}
return returnSize;
}
}
class TestViewController: UIViewController {
let testSizes: [CGSize] = [
// width > height
CGSize(width: 2715.0, height: 1920.0),
CGSize(width: 1945.0, height: 1920.0),
CGSize(width: 2278.0, height: 1920.0),
// used to provide a blank line in debug output
CGSize.zero,
// height > width
CGSize(width: 1080.0, height: 2280.0),
CGSize(width: 1080.0, height: 2160.0),
CGSize(width: 1083.0, height: 1920.0),
CGSize(width: 1080.0, height: 2160.0),
// used to provide a blank line in debug output
CGSize.zero,
// height > width problems
CGSize(width: 1300.0, height: 1920.0),
CGSize(width: 1143.0, height: 1920.0),
CGSize(width: 1281.0, height: 1920.0),
]
let imageViewSize = CGSize(width: 375, height: 667)
override func viewDidLoad() {
super.viewDidLoad()
print()
testSizes.forEach { sz in
if sz == CGSize.zero {
print()
} else {
// original size calcs
if sz.height > sz.width {
let newSZ = scaleImageWidth(sourceImageSize: sz, scaledToWidth: imageViewSize.width)
print("Orig: \(newSZ)")
} else {
let newSZ = scaleImageHeight(sourceImageSize: sz, scaledToHeight: imageViewSize.height)
print("Orig: \(newSZ)")
}
// aspectFill calc
let newSZ = sz.aspectFill(sourceSize: sz, targetSize: imageViewSize)
print("Fill: \(newSZ)")
}
}
print()
}
func scaleImageWidth(sourceImageSize: CGSize, scaledToWidth: CGFloat) -> CGSize {
let oldWidth = sourceImageSize.width
let scaleFactor = scaledToWidth / oldWidth
let newHeight = sourceImageSize.height * scaleFactor
let newWidth = oldWidth * scaleFactor
return CGSize(width: newWidth, height: newHeight)
}
func scaleImageHeight(sourceImageSize: CGSize, scaledToHeight: CGFloat) -> CGSize {
let oldheight: CGFloat = sourceImageSize.height
let scaleFactor: CGFloat = scaledToHeight / oldheight
let newWidth: CGFloat = sourceImageSize.width * scaleFactor
let newHeight: CGFloat = oldheight * scaleFactor
return CGSize(width: newWidth, height: newHeight)
}
}
这是您应该在调试控制台中得到的:
Orig: (943.1796875, 667.0)
Fill: (943.1796875, 667.0)
Orig: (675.6848958333334, 667.0)
Fill: (675.6848958333334, 667.0)
Orig: (791.3677083333333, 667.0)
Fill: (791.3677083333333, 667.0)
Orig: (375.0, 791.6666666666666)
Fill: (375.0, 791.6666666666666)
Orig: (375.0, 750.0)
Fill: (375.0, 750.0)
Orig: (375.0, 664.819944598338)
Fill: (376.2296875, 667.0)
Orig: (375.0, 750.0)
Fill: (375.0, 750.0)
Orig: (374.99999999999994, 553.8461538461538)
Fill: (451.61458333333337, 667.0)
Orig: (375.0, 629.9212598425197)
Fill: (397.0734375, 667.0)
Orig: (375.0, 562.0608899297424)
Fill: (445.0140625, 667.0)
如您所见,您发布的“有问题”尺寸得到的退货尺寸明显不同。
答案 1 :(得分:0)
将UIImageView约束设置为上,左,右,下。 现在转到UIIMageView的“属性”检查器,然后将“内容模式”属性设置为“缩放以填充”。
在这种情况下,某些图像可能会被拉伸。
答案 2 :(得分:0)
因此,经过大量尝试。阅读@DonMag
答案后,我解决了这个问题。其提到问题的原因可能是由于未考虑图像的aspect ratio
。
在我的场景中,我必须有一个UIScrollView
并让图像根据其width
和height
填充scrollView。而且它只能根据图像的纵横比在Vertically
或Horizontally
的一个方向上滚动。
要实现此目的,我仅使用了上面问题中的1个功能,即OPTION 1
,并按如下所示对其进行了修改。
func scaleImageHeight(sourceImage: UIImage, scaledToHeight: CGFloat) -> UIImage {
let oldheight: CGFloat = sourceImage.size.height
let scaleFactor: CGFloat = scaledToHeight / oldheight
let newWidth: CGFloat = sourceImage.size.width * scaleFactor
let newHeight: CGFloat = oldheight * scaleFactor
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
sourceImage.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
//This check is added as the scaling function would scale down an image to a size which was less than the width of the screen.
if newWidth < self.view.frame.width{
let differenceWidth = self.view.frame.width - newWidth
newWidth = self.view.frame.width
newHeight = newHeight+differenceWidth
}
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
因此,满足我的要求的对我有效的解决方案是始终按图像的height
缩放图像,而不管height
或width
是否大于另一个。
在缩放后,如果缩放后的图像的宽度小于屏幕宽度,那么我会将图像缩放回width
,以使其适合屏幕,而没有任何空格。这种缩放将导致height
可滚动。
注意:
ImageView
的{{1}}应该是contentMode
。