I'm trying to rotate and scale UIView
which has UIImageView
inside as subView
with one finger using UIPanGestureRecognizer
. both rotation and scaling works fine in regular situations but when view is rotated upside down then it works in opposite direction instead of scaling up it scales down and vice versa, also when rotated at corner points it kind of flickers, don't work properly. results are shown in these gifs :
here is how i'm trying to achieve this :
@objc func ScaleGest(gesture: UIPanGestureRecognizer) {
guard let gestureSuperView = gesture.view?.superview else { return }
let center = frameScaleBut.center
let touchLocation = gesture.location(in: self.view)
if gesture.state == UIPanGestureRecognizer.State.began {
self.initialDistance = distance(center, touchLocation)
} else if gesture.state == UIPanGestureRecognizer.State.changed {
let dist = distance(center, touchLocation) - initialDistance
let smallScale: CGFloat = editingMode == .sticker ? 90 : 190
let nextScale: CGSize = CGSize(width: gestureSuperView.bounds.width + dist, height: gestureSuperView.bounds.height + dist)
if (nextScale.width >= (self.view.frame.width * 0.8)) || nextScale.width <= smallScale {
return
}
gestureSuperView.bounds.size = CGSize(width: gestureSuperView.bounds.width + dist, height: gestureSuperView.bounds.height + dist)
}
}
i get distance with this method from this answer https://stackoverflow.com/a/1906659/20306199
func distance(_ a: CGPoint, _ b: CGPoint) -> CGFloat {
let xDist = a.x - b.x
let yDist = a.y - b.y
return CGFloat(sqrt(xDist * xDist + yDist * yDist))
}
this works fine when object has no rotation, but i think when object is rotated upside down it still works with same coordinates but in reality it should those values in opposite manner, can anyone please help me to understand or achieve this, thanks.
The problem is not in distance(_:_:)
function, but in the center
parameter. Your center
parameter is determined in small images coordinate space, but gestureLocation
is determined in view’s coordinate space. You can use convert(_:to:)
method to do that. You can read about it here.
UPD:
Actually you don't need to calculate distance between frameScaleBut.center
and gesture.location(in: self.view)
. Why? Because self.initialDistance
almost always will be around 0. So let dist = distance(center, touchLocation) - initialDistance
will always be positive. Instead calculate distance between gestureSuperView.center
and gesture.location(in: self.view)
. gestureSuperView
is already in view
coordinate space.