iOS-Swift-UIImage上的可点击区域

时间:2018-11-03 19:38:38

标签: ios swift uiimageview aspect-fit

我正在做一个项目,我必须在代表人体的图像上的特定区域绘制点。在Interface Builder中,我设置了一个容器UIView,该容器占据了主视图的大部分垂直中心。在该容器视图中,我放置了UIImageView并在IB中设置了图形。图形比UIImageView和容器UIView大得多,更具体地说,它更高。将UIImageView的ContentMode设置为AspectFit,因为我希望图像不显示为大于容器。

代码创建了几个CGRect实例,这些实例是用户轻按意味着某些内容的区域。当用户点击容器视图时,将使用代码确定该点是否在区域之一内,如果是,则在该区域的中心绘制一个点。

问题在于,当我在某些模拟器上运行应用程序时,区域矩形不在图像上的正确位置。例如,当我在iPhone X上运行该应用程序时,头部合适的矩形区域看起来不错。当我在iPhone XR上运行该应用程序时,矩形区域位于头部左侧。

enter image description here enter image description here

我正在使用坐标来定义区域矩形,这些区域矩形是基于例如人头在图像中的位置。我觉得这不是正确的方法,因为图像的ContentMode的AspectFit最有可能导致图像缩放以保持外观。

最重要的是,无论图像如何缩放,我都希望矩形位于正确的位置和大小。不确定我的操作方式是否有意义,因此希望提出一些建议,以提供一种更好的方法。

更新1 :UIImageView固定在周围的UIView上,因此其宽度和高度与容器一样大。由于图像比UIImageView细,因此图像在其中居中显示。在所附的图像中,紫色背景是UIImageView,显示了最上面的UIView的背景颜色。

更新2 :我检查了宽度和高度的比例,发现它们不同。宽度比例因子为1.36565656565,高度比例因子为2.104。我尝试了由Sweeper给出的两个比例因子给出的公式,但是没有运气。

3 个答案:

答案 0 :(得分:1)

您只需要做一些数学运算即可。

在原始图像上,标识用户可以点击的区域。记下相对于图像的x,y,w,h。

找出图像视图中图像缩小了多少。由于您说图像比图像视图高,因此图像的比例因子为imageViewHeight / imageHeight。我们现在将其称为scaleFactor

该区域的Y坐标也必须下降scaleFactor,因此您将regionY乘以scaleFactor即可得到newY

该区域的宽度和高度会做同样的事情,因此将它们乘以scaleFactor并得到newWidthnewHeight

相对于图像视图,该区域的X坐标有些棘手。您需要考虑通过按比例缩小图像来创建图像视图的空白空间量。 emptySpace(imageViewWidth - newWidth) / 2计算。然后,要计算相对于图像视图的新区域的X坐标,请执行emptySpace + X * scaleFactor

现在(newX, newY, newWidth, newHeight)是用户可以点击的相对于图像视图的区域!

答案 1 :(得分:0)

我为每个设备上完全相同的位置的矩形编写了此代码。 为了检查它是否是x手机,我在viewDidLoad中进行了操作,并将约束条件设置为我想要的值,并添加了标签栏大小。

@IBOutlet weak var tabMenu:          NSLayoutConstraint!
@IBOutlet weak var topConstraint:    NSLayoutConstraint!
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!

@IBOutlet weak var backgroundImg: UIImageView!
@IBOutlet weak var rectangleImg:  UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Check if it's a iPhone X
    if #available(iOS 11, *) {
        let safeArea = UIApplication.shared.delegate?.window??.safeAreaInsets

        // If its a x phone i use safe instead of superView
        guard let safe = safeArea else { return }
        if safe.bottom > 0 {
            topConstraint.constant = safe.top
            bottomConstraint.constant = safe.bottom + tabMenu.constant
        }
    }
}

override func viewDidAppear(_ animated: Bool) {

    // Here I set the rectangle to 36% of the width and height (change to what you want)
    rectangleImg.frame = CGRect(x: 0, y: 0, width: backgroundImg.frame.width * 0.36,
    height: backgroundImg.frame.height * 0.36)

    // Last I put the rectangle in the center of background image
    rectangleImg.center.x = backgroundImg.center.x
    rectangleImg.center.y  = backgroundImg.center.y

}

希望此代码可以帮助您!

答案 2 :(得分:0)

问题的根源在于,我将UIImageView的四个侧面固定到了其容器视图。当设备的宽度改变时,它会正确缩放图像,但会导致图形“拉伸”。例如,这导致头的宽度增加。我现在已经通过锁定图像的宽度来解决此问题,因此无论使用什么设备,我从原始图像得出的坐标都保持不变。

对于那些阅读本文的人来说,这听起来似乎不是很多解决方案,但是由于我有一个非常激进的截止日期,因此我必须坚持下去。我已经在多个设备模拟器上对其进行了测试,并且可以正常工作。将来我可能不得不重新审视此问题,但目前为止,它正在起作用。

我还使用了这个问题的答案来重新编写代码:create a clickable body diagram