Как найти новый центр UIImageView после масштабирования? - PullRequest
0 голосов
/ 05 ноября 2019

Я создаю приложение, в котором пользователь может добавить изображение в «холст», а также изменить его размер и переместить изображение, используя средства распознавания жестов и панорамирования. Представление изображения является пользовательским, которое я создал, используя эту статью: Пути Безье и Распознаватели жестов

Это работает очень хорошо. Изображение изменяется и перемещается очень плавно. Я могу захватить центр и размер изображения после жестов панорамирования и сжатия. Проблема в том, что после сохранения размера и координат изображения оно не соответствует тем, которые я загружаю обратно в «холст». Это как если бы центр был смещен на число пикселей "X".

Вот мой код для создания изменяемого размера и подвижного изображения:

'' '

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")
    }
}

'' '

И вот как я загружаю его обратно в «холст» и сохраняю его обратно в 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)
                        }
                    }
                }

' ''

Вот изображение того, что происходит, когда я перемещаю изображение по холсту: Это первоеНа рисунке показано, где я перестал перемещать изображение в: Moving, pan still happening

Это изображение показывает, куда было загружено изображение после сохранения размера и координат: enter image description here

Желаемый результат:

  • При сжатии, панорамировании и сохранении изображения, а затем загрузке изображение сохраняет свои текущие координаты и размер на холсте.

РЕДАКТИРОВАТЬ: Следует также отметить, что смещение изображения при его перемещении происходит только после "масштабирования

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...