【问题标题】:Zooming into an image from user's touch point with UIScrollView in Swift在 Swift 中使用 UIScrollView 从用户的触摸点放大图像
【发布时间】:2016-08-09 16:03:30
【问题描述】:

以下 Swift 代码管理在 UIScrollView 内放大和缩小 UIImage

双击时,图像放大到中心并缩小到中心。

问题:

需要对代码进行哪些更改才能将放大点设置为用户在屏幕上触摸的图像区域的中心?

(例如,如果用户双击图像的左上角,图像会相应地放大到图像的左上角。)

class ScrollViewController: UIViewController, UIScrollViewDelegate {
    var scrollView: UIScrollView!
    var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView = UIImageView(image: UIImage(named: "image.png"))

        scrollView = UIScrollView(frame: view.bounds)
        scrollView.backgroundColor = UIColor.blackColor()
        scrollView.contentSize = imageView.bounds.size
        scrollView.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]

        scrollView.contentOffset = CGPoint(x: 1000, y: 450)

        scrollView.addSubview(imageView)
        view.addSubview(scrollView)

        scrollView.delegate = self
        setZoomScale()
        setupGestureRecognizer()
    }

    func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
        return imageView
    }

    override func viewWillLayoutSubviews() {
        setZoomScale()
    }

    func setZoomScale() {
        let imageViewSize = imageView.bounds.size
        let scrollViewSize = scrollView.bounds.size
        let widthScale = scrollViewSize.width / imageViewSize.width
        let heightScale = scrollViewSize.height / imageViewSize.height

        scrollView.minimumZoomScale = min(widthScale, heightScale)
        scrollView.zoomScale = 1.0
    }

    func scrollViewDidZoom(scrollView: UIScrollView) {
        let imageViewSize = imageView.frame.size
        let scrollViewSize = scrollView.bounds.size
        let verticalPadding = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
        let horizontalPadding = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0

        scrollView.contentInset = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
    }

    func setupGestureRecognizer() {
        let doubleTap = UITapGestureRecognizer(target: self, action: "handleDoubleTap:")
        doubleTap.numberOfTapsRequired = 2
        scrollView.addGestureRecognizer(doubleTap)
    }

    func handleDoubleTap(recognizer: UITapGestureRecognizer) {
        if (scrollView.zoomScale > scrollView.minimumZoomScale) {
            scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
        } else {
            scrollView.setZoomScale(scrollView.maximumZoomScale, animated: true)
        }
    }
}

【问题讨论】:

    标签: ios swift optimization uiscrollview uiimage


    【解决方案1】:

    根据this post。对我来说效果很好。

    func handleDoubleTap(recognizer: UITapGestureRecognizer) {
        if (scrollView.zoomScale > scrollView.minimumZoomScale) {
            scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
        } else {
            let touchPoint = recognizer.locationInView(view)
            let scrollViewSize = scrollView.bounds.size
    
            let width = scrollViewSize.width / scrollView.maximumZoomScale
            let height = scrollViewSize.height / scrollView.maximumZoomScale 
            let x = touchPoint.x - (width/2.0)
            let y = touchPoint.y - (height/2.0)
    
            let rect = CGRectMake(x, y, width, height)
            scrollView.zoomToRect(rect, animated: true)
        }
    }
    

    【讨论】:

    • 感谢@Wei Jay 发布您的答案。不幸的是,这仅在UIScrollView 包含与屏幕尺寸相同的内容时才有效。例如,它不适用于在屏幕上更宽、更高或放大的UIImageView。当双击该较大类型的内容时,对触摸点的缩放不正确,它会放大到内容的不同部分。我要修补,但如果您有任何其他建议,请更新代码?谢谢。干杯。
    • @user4806509 我也在尝试在 Swift 3 中解决这个问题。运气好吗?
    【解决方案2】:

    这是一个 Swift 2.3 函数,用于返回可缩放 UIScrollView 内的触摸位置:

    • 内含 UIImageView 的 UIScrollView
    • 缩放与否 - scrollView.zoomScale
    • imageView.contentMode = .ScaleAspectFit
    • 图片可以比imageView和scrollView更大、更高分辨率
    • 图像的任何形状,纵向、横向或正方形

    imageView.contentMode = .ScaleAspectFit

    //import AVFoundation // needed for AVMakeRectWithAspectRatioInsideRect()
    
    func getLocationOfTouchInImageInScrollView(paintLocation:CGPoint)->CGPoint {
    
        let imageSize = imageViewInScrollView.image!.size
        let imageFrame = scrollView.frame
        let imageRect = AVMakeRectWithAspectRatioInsideRect(imageSize, imageFrame)
        let imageHeightToViewHeight = max(imageSize.height, imageSize.width) / imageFrame.size.height
    
        let px = (max(0, min(imageSize.width, ((paintLocation.x - imageRect.origin.x) * imageHeightToViewHeight))))
        let py = (max(0, min(imageSize.height, ((paintLocation.y - imageRect.origin.y ) * imageHeightToViewHeight))))
        var imageTouchPoint = CGPointMake(CGFloat(px), CGFloat(py))
    
        return imageTouchPoint
    }
    

    我花了几天时间写这篇文章,因为我无法弄清楚 imageHeightToViewHeight 变量,以为还有其他有趣的事情发生。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-23
      • 1970-01-01
      • 2015-06-30
      • 2015-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多