Reputation: 1351
I am trying to rotate an ImageView I have depending on the X coordinate it is on. Basically, I want it to have a rotation of 0º when x = 300 and a rotation of 180º when x = 190.
I had to program the UIPanGestureRecognizer programmatically. Here is the code I currently have right now:
@objc func personDrag(recognizer: UIPanGestureRecognizer) {
let rotationSub: CGFloat = 1
let translation = recognizer.translation(in: rView)
if let view = recognizer.view {
view.center = CGPoint(x:view.center.x + translation.x, y:view.center.y + translation.y)
view.transform = view.transform.rotated(by: CGFloat.pi - rotationSub)
}
recognizer.setTranslation(CGPoint.zero, in: rView)
}
I was going to attempt to change the rotation degree by 1 every time they panned but it doesn't really work/make sense. Any help would be appreciated. Thank you so much!
Cheers, Theo
Upvotes: 3
Views: 2306
Reputation: 1
Using Swift5
Programmatically
Rotate view by single point touch
import UIKit
class ViewController: UIViewController {
//Variable for rotating
private var deltaAngle:CGFloat = 0
let squareView : UIView = {
let anyView = UIView()
anyView.backgroundColor = .red
anyView.isUserInteractionEnabled = true
anyView.isMultipleTouchEnabled = true
return anyView
}()
let rotateButton : UIButton = {
let button = UIButton()
button.backgroundColor = .black
button.setImage(UIImage(systemName: "rotate.right"), for: .normal)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
squareView.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
rotateButton.frame = CGRect(x: 0, y: squareView.frame.height-30, width: 30, height: 30)
squareView.center = view.center
view.addSubview(squareView)
squareView.addSubview(rotateButton)
let PanToRotate = UIPanGestureRecognizer(target: self, action: #selector(handleRotateGesture(_:)))
rotateButton.addGestureRecognizer(PanToRotate)
}
@objc func handleRotateGesture(_ recognizer : UIPanGestureRecognizer){
let touchLocation = recognizer.location(in: squareView.superview)
let center = squareView.center
switch recognizer.state{
case .began :
self.deltaAngle = atan2(touchLocation.y - center.y, touchLocation.x - center.x) - atan2(squareView.transform.b, squareView.transform.a)
case .changed:
let angle = atan2(touchLocation.y - center.y, touchLocation.x - center.x)
let angleDiff = self.deltaAngle - angle
squareView.transform = CGAffineTransform(rotationAngle: -angleDiff)
default: break
}
}
}
Upvotes: 0
Reputation: 1287
I hope this will help you.
@objc func rotateViewPanGesture(_ recognizer: UIPanGestureRecognizer) {
touchLocation = recognizer.location(in: superview)
let center = CGRectGetCenter(frame)
switch recognizer.state {
case .began:
deltaAngle = atan2(touchLocation!.y - center.y, touchLocation!.x - center.x) - CGAffineTrasformGetAngle(transform)
initialBounds = bounds
initialDistance = CGpointGetDistance(center, point2: touchLocation!)
case .changed:
let ang = atan2(touchLocation!.y - center.y, touchLocation!.x - center.x)
let angleDiff = deltaAngle! - ang
let a = transform.a
let b = transform.b
let c = transform.c
let d = transform.d
let sx = sqrt(a * a + b * b)
let sy = sqrt(c * c + d * d)
let currentScale = CGPoint(x: sx, y: sy)
let scale = CGAffineTransform(scaleX: currentScale.x, y: currentScale.y)
self.transform = scale.rotated(by: -angleDiff)
layoutIfNeeded()
case .ended:
print("end gesture status")
default:break
}
}
Upvotes: 0
Reputation: 2443
You can build your implementation on this:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var imageview: UIImageView!
private var currentRotation: Rotation = .none
/* Certain rotation points (rotation of 0º when x = 300 and a rotation of 180º when x = 190) */
enum Rotation {
case none, xPoint190, xPoint300
}
override func viewDidLoad() {
super.viewDidLoad()
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
imageview.addGestureRecognizer(gestureRecognizer)
imageview.isUserInteractionEnabled = true
}
@IBAction func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
guard gestureRecognizer.state == .began || gestureRecognizer.state == .changed else {
return
}
guard let imgView = gestureRecognizer.view else {
return
}
let translation = gestureRecognizer.translation(in: self.view)
imgView.center = CGPoint(x: imgView.center.x + translation.x, y: imgView.center.y + translation.y)
gestureRecognizer.setTranslation(CGPoint.zero, in: self.view)
let angle: CGFloat = self.degreesToRadians(180.0)
/* After reaching x point case - rotating and setting rotation occured to prohibit further rotation */
if imgView.layer.frame.origin.x <= 190, currentRotation != .xPoint190 {
imgView.transform = imgView.transform.rotated(by: angle)
currentRotation = .xPoint190
} else if imgView.layer.frame.origin.x >= 300, currentRotation != .xPoint300 {
imgView.transform = imgView.transform.rotated(by: angle)
currentRotation = .xPoint300
}
private func degreesToRadians(_ deg: CGFloat) -> CGFloat {
return deg * CGFloat.pi / 180
}
}
Upvotes: 4