如何将图像的位置和比例转移到其他视图?

时间:2017-08-17 08:20:53

标签: ios swift xcode

我在每个视图中都有两个视图和一个图像。在第一个视图中,我可以使用手势缩放,旋转和平移图像。我想记录这些变换中的每一个并将它们传输到第二个视图中的图像,这样第二个图像就会出现在与第一个视图中第一个图像完全相同的位置,但是会有相反的缩放(如果第一个图像按比例放大,然后第二个需要缩小相同的量。)

以下代码仅在图像平移或旋转但不缩放时才有效。缩放完全改变了图像中心的位置,代码不再正常工作。如何修复它,使第二个图像的中心位置与第一个图像的中心位置相同而不管缩放?

这是第一个视图的视图控制器:

import UIKit

class FirstViewController: UIViewController {

// MARK: Properties
@IBOutlet weak var photo: UIImageView!

// Variables for scaling
var max_scale: CGFloat = 3.0
var min_scale: CGFloat = 0.2
var current_scale: CGFloat = 1.0
var lastScale: CGFloat = 0.0

// Position variables
var translate_x: CGFloat = 0.0
var translate_y: CGFloat = 0.0
var scale: CGFloat = 1.0
var angle: CGFloat = 0.0

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

// MARK: Gesture actions

@IBAction func pinchGesture(_ gestureRecognizer: UIPinchGestureRecognizer) {

    // Move the achor point of the view's layer to the touch point
    // so that scaling the view and the layer becames simpler.
    self.adjustAnchorPoint(gestureRecognizer: gestureRecognizer)

    // Scale the view by the current scale factor.

    if(gestureRecognizer.state == .began) {
        // Reset the last scale, necessary if there are multiple objects with different scales
        lastScale = gestureRecognizer.scale
    }
    if (gestureRecognizer.state == .began || gestureRecognizer.state == .changed) {
        let currentScale = gestureRecognizer.view!.layer.value(forKeyPath:"transform.scale")! as! CGFloat
        // Constants to adjust the max/min values of zoom
        let kMaxScale:CGFloat = 15.0
        let kMinScale:CGFloat = 1.0
        var newScale = 1 -  (lastScale - gestureRecognizer.scale)
        newScale = min(newScale, kMaxScale / currentScale)
        newScale = max(newScale, kMinScale / currentScale)
        let transform = (gestureRecognizer.view?.transform)!.scaledBy(x: newScale, y: newScale);
        gestureRecognizer.view?.transform = transform
        lastScale = gestureRecognizer.scale  // Store the previous scale factor for the next pinch gesture call
        scale = currentScale
    }
}

@IBAction func panGesture(_ gestureRecognizer: UIPanGestureRecognizer) {
    // Move the achor point of the view's layer to the touch point
    // so that movig the view becomes simpler.
    let piece = gestureRecognizer.view
    self.adjustAnchorPoint(gestureRecognizer: gestureRecognizer)

    // Apply the pan to the view's transform.
    if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
        //print((photo.frame.origin.x), (photo.frame.origin.y))
        // Get the distance moved since the last call to this method.
        let translation = gestureRecognizer.translation(in: piece?.superview)

        // Set the translation point to zero so that the translation distance
        // is only the change since the last call to this method.
        piece?.center = CGPoint(x: ((piece?.center.x)!+translation.x), y: ((piece?.center.y)!+translation.y))
        translate_x = (piece?.center.x)!
        translate_y = (piece?.center.y)!
        gestureRecognizer.setTranslation(CGPoint.zero, in: piece?.superview)
    }
}

@IBAction func rotationGesture(_ gestureRecognizer: UIRotationGestureRecognizer) {
    // Move the achor point of the view's layer to the center of the
    // user's two fingers. This creates a more natural looking rotation.
    self.adjustAnchorPoint(gestureRecognizer: gestureRecognizer)

    // Apply the rotation to the view's transform.
    if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
        gestureRecognizer.view?.transform = (gestureRecognizer.view?.transform.rotated(by: gestureRecognizer.rotation))!
        // Set the rotation to 0 to avoid compouding the
        // rotation in the view's transform.
        angle += gestureRecognizer.rotation
        gestureRecognizer.rotation = 0.0
    }
}

func adjustAnchorPoint(gestureRecognizer : UIGestureRecognizer) {
    if gestureRecognizer.state == .began {
        let view = gestureRecognizer.view
        let locationInView = gestureRecognizer.location(in: view)
        let locationInSuperview = gestureRecognizer.location(in: view?.superview)

        // Move the anchor point to the the touch point and change the position of the view
        view?.layer.anchorPoint = CGPoint(x: (locationInView.x / (view?.bounds.size.width)!), y: (locationInView.y / (view?.bounds.size.height)!))
        view?.center = locationInSuperview
    }
}

// MARK: - Navigation

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let resultView = segue.destination as! SecondViewController
    resultView.finalImage = photo.image!

    resultView.translate_x_ = photo.frame.origin.x + UIScreen.main.bounds.width / 2
    resultView.translate_y_ = photo.frame.origin.y + UIScreen.main.bounds.height / 2
    resultView.scale_ = scale
    resultView.angle_ = angle
}
}

然后将位置参数传送到第二个视图控制器,如下所示:

override func viewDidLoad() {
    super.viewDidLoad()

    editedPhoto.image = finalImage

    // Translate
    editedPhoto.center = CGPoint(x: (UIScreen.main.bounds.width / 2), y: (UIScreen.main.bounds.height / 2))
    editedPhoto.center = CGPoint(x: (translate_x_), y: (translate_y_))

    // Scale
    editedPhoto.transform = editedPhoto.transform.scaledBy(x: (1/scale_), y: (1/scale_))

    // Rotate
    editedPhoto.transform = editedPhoto.transform.rotated(by: angle_)
}

1 个答案:

答案 0 :(得分:1)

嗯......我试着按原样运行代码,但我必须错过设置步骤。如果我不对视图进行任何更改(无拖动,捏合或旋转),则下一个查看器中的视图将不在适当位置。

然而....

我认为您遇到了麻烦,因为您没有考虑更改.layer.anchorPoint

试试这个 -

SecondViewController中,添加一个新属性(将在准备segue期间设置):

var anchorPoint_: CGPoint = CGPoint.zero

然后,在viewDidLoad()

override func viewDidLoad() {
    super.viewDidLoad()

    editedPhoto.image = finalImage

    // add this line
    editedPhoto.layer.anchorPoint = anchorPoint_

    // Translate
    editedPhoto.center = CGPoint(x: (translate_x_), y: (translate_y_))

    // Scale
    editedPhoto.transform = editedPhoto.transform.scaledBy(x: (1/scale_), y: (1/scale_))

    // Rotate
    editedPhoto.transform = editedPhoto.transform.rotated(by: angle_)

}

FirstViewController中,准备segue成为:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let resultView = segue.destination as! SecondViewController
    resultView.finalImage = photo.image!

    resultView.anchorPoint_ = photo.layer.anchorPoint

    resultView.translate_x_ = photo.center.x
    resultView.translate_y_ = photo.center.y

    resultView.scale_ = scale
    resultView.angle_ = angle
}

认为应该解决这个问题。