首页 > 解决方案 > 缩放后如何找到 UIImageView 的新中心?

问题描述

我正在创建一个应用程序,用户可以在其中将图像添加到“画布”并使用捏合和平移手势识别器调整图像大小和移动图像。图像视图是我使用本文创建的自定义视图: Bezier Paths and Gesture Recognizers

这真的很好用。图像调整大小和移动非常流畅。在平移和捏合手势之后,我可以捕获图像的中心和大小。问题是,在我保存图像的大小和坐标后,当我将其加载回“画布”时,它并不尊重这些。就好像中心偏移了“X”个像素。

这是我制作可调整大小和可移动的图像视图的代码:

'''</p>

import UIKit
import Foundation

class MovableImage: UIImageView {
    let size: CGFloat = 150.0
    var imageMovedHandler:((_ x: CGFloat, _ y: CGFloat) -> ())?
    var imageDeletedHandler:((_ delete: Bool) -> ())?
    var longPressHandler:((_ selected: Bool) -> ())?
    var imageSizeChangedHandler:((_ newImageView: MovableImage) -> ())?
    let deleteButton = UIButton(type: .close)

    init(origin: CGPoint) {
        super.init(frame: CGRect(x: origin.x, y: origin.y, width: size, height: size)) //

        debugCenterDot()
        initGestureRecognizers()
    }

//added a dot to try and understand what is happening with the "center" of the imageview, but it didn't show in the center of the imageview
    func debugCenterDot() {
        let dot = UIBezierPath(ovalIn: CGRect(x: self.center.x, y: self.center.y, width: 15, height: 15))
        let dotLayer = CAShapeLayer()
        dotLayer.path = dot.cgPath
        dotLayer.strokeColor = UIColor.yellow.cgColor

        self.layer.addSublayer(dotLayer)
        self.setNeedsDisplay()
    }

    internal func addButton() {
        deleteButton.tintColor = UIColor.red
        deleteButton.backgroundColor = UIColor.white
        deleteButton.addTarget(self, action: #selector(deleteSelf(sender:)), for: .touchUpInside)
        deleteButton.frame = .zero //CGRect(x: 8, y: 8, width: 15, height: 15)
        deleteButton.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(deleteButton)
        NSLayoutConstraint.activate([
            deleteButton.widthAnchor.constraint(equalToConstant: 15),
            deleteButton.widthAnchor.constraint(equalTo: deleteButton.heightAnchor),
            deleteButton.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: 8),
            deleteButton.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 8),
        ])


    }

    @objc func deleteSelf(sender: UIButton) {
        imageDeletedHandler?(true)
        self.removeFromSuperview()
    }

    func initGestureRecognizers() {
        let panGR = UIPanGestureRecognizer(target: self, action: #selector(didPan(panGR:)))
        addGestureRecognizer(panGR)

        let pinchGR = UIPinchGestureRecognizer(target: self, action: #selector(didPinch(pinchGR:)))
        addGestureRecognizer(pinchGR)

        let longPressGR = UILongPressGestureRecognizer(target: self, action: #selector(didLongPress(longPressGR:)))
        longPressGR.minimumPressDuration = 1
        addGestureRecognizer(longPressGR)

    }

    @objc func didLongPress(longPressGR: UILongPressGestureRecognizer) {
        self.superview!.bringSubviewToFront(self)
        self.layer.borderWidth = 2
        self.layer.borderColor = UIColor.red.cgColor

        addButton()
        longPressHandler?(true)
    }

    @objc func didPan(panGR: UIPanGestureRecognizer) {
        self.superview!.bringSubviewToFront(self)

        if self.layer.borderWidth == 2 {
            let translation = panGR.translation(in: self)

            print("BEFORE PAN: \(self.center)")

            self.center.x += translation.x
            self.center.y += translation.y

            print("AFTER PAN: \(self.center)")

            panGR.setTranslation(CGPoint.zero, in: self)
            if panGR.state == .ended {
                imageMovedHandler?(self.center.x, self.center.y)
                self.layer.borderWidth = 0
                self.layer.borderColor = nil
                self.deleteButton.removeFromSuperview()
            }
        }
    }

    @objc func didPinch(pinchGR: UIPinchGestureRecognizer) {
        self.superview?.bringSubviewToFront(self)

        if self.layer.borderWidth == 2 {
            let scale = pinchGR.scale

            self.transform = CGAffineTransform(scaleX: scale, y: scale)

            if pinchGR.state == .ended {
                imageSizeChangedHandler?(self)
            }
        }
    }

    func scaleOf(transform: CGAffineTransform) -> CGPoint {
        let xscale = sqrt(transform.a * transform.a + transform.c * transform.c)
        let yscale = sqrt(transform.b * transform.b + transform.d * transform.d)

        return CGPoint(x: xscale, y: yscale)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

'''</p>

这是我如何将它加载回“画布”并将其保存回CoreData(将函数保存在靠近加载函数底部的闭包中):

'''

    func loadImages(new: Bool, enableInteraction: Bool) {
            let pagePhotos = LoadPagePhotos()
            var pageImages: [NSManagedObject] = []
            var x: CGFloat?
            var y: CGFloat?
            var width: CGFloat?
            var height: CGFloat?
            var image: UIImage?

            if isYear {
                pageImages = pagePhotos.resetYearPhotosPositions(journalName: journalName, yearPosition: yearPosition)
            } else {
                pageImages = pagePhotos.resetPhotosPositions(journalName: journalName, monthName: monthName, weekPosition: positionWeek)
            }

            scrollView.mainView.newImages.forEach { i in
                i.removeFromSuperview()
            }
            scrollView.mainView.newImages.removeAll()

            if pageImages.count > 0 {
                pageImages.forEach{ (photo) in
                    x = CGFloat((photo.value(forKey: "pageImageX") as? Float)!)
                    y = CGFloat((photo.value(forKey: "pageImageY") as? Float)!)
                    height = CGFloat((photo.value(forKey: "pageImageSizeHeight") as? Float)!)
                    width = CGFloat((photo.value(forKey: "pageImageSizeWidth") as? Float)!)
                    image = photo.value(forKey: "image") as? UIImage

                    let thisImage: MovableImage = MovableImage(origin: CGPoint.zero)
                    thisImage.contentMode = .scaleAspectFit
                    thisImage.center = CGPoint(x: x!, y: y!)
                    thisImage.image = image!
                    thisImage.frame.size.height = height!
                    thisImage.frame.size.width = width!

                    scrollView.mainView.addSubview(thisImage)
                    scrollView.mainView.newImages.append(thisImage)
                    if enableInteraction {
                        thisImage.isUserInteractionEnabled = true
                    } else {
                        thisImage.isUserInteractionEnabled = false
                    }
                    thisImage.layer.zPosition = 1
                    thisImage.layer.borderWidth = 0

                    if new {
                        imageOptionsMenuView.isHidden = false
                    } else {
                        imageOptionsMenuView.isHidden = true
                    }
                    movableImage = thisImage
//for clarity sake I moved the save functions to separate block here in stack overflow so it is easier to read
            }

        }

'''

闭包“imageMovedHandler”和“imageSizeChangedHandler”用于检测何时完成移动和调整大小,并将图像保存到CoreData。他们来了:

'''

if movableImage != nil {                        


movableImage?.imageMovedHandler = { [unowned self] (x, y) in
                    if self.isYear {
                        if self.scrollView.mainView.newImages.count > 0 {
                            for (idx, i) in self.scrollView.mainView.newImages.enumerated() {
                                if i.layer.borderWidth == 2 {
                                    let id = idx + 1
                                    _ = LoadPagePhotos().updateYearPhoto(journalName: self.journalName, yearPosition: self.yearPosition, pageImageId: id, imageHeight: Float(i.frame.size.height), imageWidth: Float(i.frame.size.width), imageX: Float(i.center.x), imageY: Float(i.center.y), pagePhoto: i.image!, photoPath: nil)
                                }
                            }
                        }
                    } else {
                        if self.scrollView.mainView.newImages.count > 0 {
                            for (idx, i) in self.scrollView.mainView.newImages.enumerated() {
                                if i.layer.borderWidth == 2 {
                                    let id = idx + 1
                                    _ = LoadPagePhotos().updatePhoto(journalName: self.journalName, monthName: self.monthName, weekPosition: self.positionWeek, pageImageId: id, imageHeight: Float(i.frame.size.height), imageWidth: Float(i.frame.size.width), imageX: Float(i.center.x), imageY: Float(i.center.y), pagePhoto: i.image!, photoPath: nil)
                                }
                            }
                        }
                    }
                    self.loadImages(new: false, enableInteraction: true)
                }

    movableImage?.imageSizeChangedHandler = { [unowned self] (newImageView) in
                                var id = 0
                                var img = 0
                                if self.isYear {
                                    if self.scrollView.mainView.newImages.count > 0 {

                                    for (idx, i) in self.scrollView.mainView.newImages.enumerated() {
                                        if i.layer.borderWidth == 2 {
                                            id = idx + 1
                                            img = idx
                                        }
                                    }
                                    self.scrollView.mainView.newImages[img] = newImageView                                
                                    _ = LoadPagePhotos().updateYearPhoto(journalName: self.journalName, yearPosition: self.yearPosition, pageImageId: id, imageHeight: Float(newImageView.frame.size.height), imageWidth: Float(newImageView.frame.size.width), imageX: Float(newImageView.center.x), imageY: Float(newImageView.center.y), pagePhoto: newImageView.image!, photoPath: nil)
                                }
                            } else {
                                if self.scrollView.mainView.newImages.count > 0 {
                                    for (idx, i) in self.scrollView.mainView.newImages.enumerated() {
                                        if i.layer.borderWidth == 2 {
                                            id = idx + 1
                                            img = idx
                                        }
                                    }
                                    self.scrollView.mainView.newImages[img] = newImageView
                                    _ = LoadPagePhotos().updatePhoto(journalName: self.journalName, monthName: self.monthName, weekPosition: self.positionWeek, pageImageId: id, imageHeight: Float(newImageView.frame.size.height), imageWidth: Float(newImageView.frame.size.width), imageX: Float(newImageView.center.x), imageY: Float(newImageView.center.y), pagePhoto: newImageView.image!, photoPath: nil)
                                }
                            }
                            self.loadImages(new: false, enableInteraction: true)
                        }
                    }
                }

'''

这是我在画布周围移动图像时发生的情况的图像:第一张图像显示了我停止将图像移动到的位置: 移动,平移仍在发生

此图像显示了保存大小和坐标后图像的加载位置: 在此处输入图像描述

期望的结果是:

编辑: 还应注意,移动时图像的偏移仅发生在“缩放”之后

标签: iosswiftcore-dataimageview

解决方案


推荐阅读