iOS Swift:使用GestureRecognizer获取UIImage坐标偏移问题
问题分析与解决方案
问题原因
你当前的坐标转换逻辑直接用UIImageView的frame宽高计算比例,但设置.scaleAspectFit后,图片会在UIImageView内部居中显示。当图片宽高比与UIImageView宽高比不一致时,UIImageView的左右或上下会出现空白区域。你的X坐标偏移,说明图片宽高比大于UIImageView的宽高比,导致左右出现空白,而你直接把触摸点除以UIImageView宽度,把空白区域的比例也算进了坐标转换,所以点击边缘时X坐标严重偏移;Y方向正常是因为图片缩放后的高度刚好填满UIImageView的高度,空白区域的影响未体现。
另外,你的布局给UIImageView设置了固定高度约束(0.4*view.frame.size.height),结合.scaleAspectFit,图片在Y方向刚好适配高度,所以Y方向比例计算正确,但X方向因图片宽度小于UIImageView宽度,存在左右空白,导致比例计算错误。
修正后的坐标转换代码
修改didTapImage函数,先计算图片在UIImageView中的实际显示区域,再基于该区域进行坐标转换:
@IBAction func didTapImage(tapGestureRecognizer: UITapGestureRecognizer) { guard let image = imageView.image else { return } let touchPoint = tapGestureRecognizer.location(in: imageView) // 计算图片在ImageView中的实际显示区域 let imageSize = image.size let viewSize = imageView.bounds.size let widthRatio = viewSize.width / imageSize.width let heightRatio = viewSize.height / imageSize.height let scale = min(widthRatio, heightRatio) // 图片实际显示的尺寸 let scaledImageWidth = imageSize.width * scale let scaledImageHeight = imageSize.height * scale // 图片在ImageView中的偏移量(居中显示时的空白区域) let xOffset = (viewSize.width - scaledImageWidth) / 2 let yOffset = (viewSize.height - scaledImageHeight) / 2 // 判断触摸点是否在图片实际区域内 guard touchPoint.x >= xOffset && touchPoint.x <= xOffset + scaledImageWidth, touchPoint.y >= yOffset && touchPoint.y <= yOffset + scaledImageHeight else { print("点击在图片空白区域") return } // 计算相对于图片的坐标比例 let x_prop = (touchPoint.x - xOffset) / scaledImageWidth let y_prop = (touchPoint.y - yOffset) / scaledImageHeight let new_x = x_prop * imageSize.width let new_y = y_prop * imageSize.height print("点击原始图片坐标: x: \(new_x) y: \(new_y)") // 调用绘制十字线的方法 markImage(x_prop: x_prop, y_prop: y_prop) }
额外注意事项
- 你的布局代码中重复添加了
contentView、stackView到父视图,需要删除重复代码:// 以下为重复代码,保留一份即可 // contentView.contentMode = .scaleAspectFit // contentView.addSubview(stackView) // scrollView.addSubview(contentView) // view.addSubview(scrollView) markImage函数中UIGraphicsBeginImageContextWithOptions的scale参数建议使用image.scale,保持和原始图片一致的缩放比例:UIGraphicsBeginImageContextWithOptions(imageSize, false, image.scale)
内容的提问来源于stack exchange,提问作者rdk
相关产品推荐
相关产品推荐

