Swift 旋转手势产生不希望的旋转

Swift 旋转手势产生不希望的旋转,swift,uiimageview,rotation,uigesturerecognizer,Swift,Uiimageview,Rotation,Uigesturerecognizer,我需要旋转一个UIImageview对用户的运动只用一个手指的运动。为此,我使用旋转手势,然后用以下代码覆盖触摸: override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { let touch = touches.first if touch!.view === rotateImageView { let position = touch!.loc

我需要旋转一个UIImageview对用户的运动只用一个手指的运动。为此,我使用旋转手势,然后用以下代码覆盖触摸:

  override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

    let touch = touches.first
    if touch!.view === rotateImageView {
        let position = touch!.locationInView(self.view)

        let target = rotateImageView.center
        let angle = atan2(target.y-position.y, target.x-position.x)
        rotateImageView.transform = CGAffineTransformMakeRotation(angle)
    }
  }
覆盖功能触摸移动(触摸:设置,带事件:UIEvent?){
让我们先接触
如果触摸!.view==rotateImageView{
让位置=触摸!.locationInView(self.view)
让目标=rotateImageView.center
让角度=atan2(target.y-position.y,target.x-position.x)
rotateImageView.transform=CGAffineTransformMakeRotation(角度)
}
}
只要用户停止触摸屏幕并在屏幕的另一部分进行运动,此功能就可以工作。在这种情况下,当用户开始移动手指时,UIImageview会在不希望的位置旋转。我需要保持UIImageview的原始旋转位置以避免出现这种情况,但我不知道如何做到这一点

这个gif显示了我拥有的项目原型的当前行为。正如你所看到的,当我开始在右侧旋转时,火焰图标突然出现在接触点附近,这就是我想要阻止的

2016年8月23日更新

我使用了Matt和Dasem建议使用CGAffineTransformRotate,但我仍然看到了跳跃。我使用了DASM代码,并对我的项目进行了如下调整(如果调整错误,请告诉我):

覆盖函数触摸开始(触摸:设置,withEvent事件:UIEvent?){
原点=(touch.first?.locationInView(self.view))!
//保存当前变换
TENTRANSFORM=rotateImageView.transform
}
覆盖功能触摸移动(触摸:设置,带事件:UIEvent?){
让touchPoint=touchs.first?.locationInView(self.view)
xOffSet=CGVector(dx:(origin.x)-rotateImageView.center.x,dy:(origin.x)-rotateImageView.center.y)
yOffSet=CGVector(dx:touchPoint!.x-rotateImageView.center.x,dy:touchPoint!.y-rotateImageView.center.y)
让角度=atan2(yOffSet.dy,yOffSet.dx)-atan2(xOffSet.dy,xOffSet.dx)
rotateImageView.transform=CGAffineTransformRotate(尝试变换,角度)
}
当用户触摸触摸屏的不同区域时,此更改会产生类似的效果。在这个gif中,我更改了图像并删除了图标,使效果更加明显

使用解决方案更新

使用Jasem update重新应用代码,它成功了,下面的代码在不使用子类的情况下解决了这个问题

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    origin = (touches.first?.locationInView(self.view))!
    xOffSet = CGVector(dx:(origin.x)-rotateImageView.center.x, dy:(origin.y) - rotateImageView.center.y)
    startingAngle = atan2(xOffSet.dy,xOffSet.dx)

    //save the current transform
    tempTransform = rotateImageView.transform
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

    let touchPoint = touches.first?.locationInView(self.view)
    yOffSet = CGVector(dx:touchPoint!.x - rotateImageView.center.x, dy:touchPoint!.y - rotateImageView.center.y)
    let angle = atan2(yOffSet.dy,yOffSet.dx)

    let deltaAngle = angle - startingAngle!
    rotateImageView.transform = CGAffineTransformRotate(tempTransform, deltaAngle)
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    startingAngle = nil
}

//reset in case drag is cancelled
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
    rotateImageView.transform = tempTransform
    startingAngle = nil
}
覆盖函数触摸开始(触摸:设置,withEvent事件:UIEvent?){
原点=(touch.first?.locationInView(self.view))!
xOffSet=CGVector(dx:(origin.x)-rotateImageView.center.x,dy:(origin.y)-rotateImageView.center.y)
启动角度=atan2(xOffSet.dy,xOffSet.dx)
//保存当前变换
TENTRANSFORM=rotateImageView.transform
}
覆盖功能触摸移动(触摸:设置,带事件:UIEvent?){
让touchPoint=touchs.first?.locationInView(self.view)
yOffSet=CGVector(dx:touchPoint!.x-rotateImageView.center.x,dy:touchPoint!.y-rotateImageView.center.y)
让角度=atan2(yOffSet.dy,yOffSet.dx)
让deltaAngle=角度-开始角度!
rotateImageView.transform=CGAffineTransformRotate(尝试转换,三角洲角度)
}
覆盖func touchesEnded(触摸:设置,withEvent事件:UIEvent?){
起动角=零
}
//取消拖动时重置
覆盖功能触摸已取消(触摸:设置?,带事件:UIEvent?){
rotateImageView.transform=truetransform
起动角=零
}

问题是你在说

rotateImageView.transform = CGAffineTransformMakeRotation(angle)
因此,图像视图已经进行的任何变换(从上一次旋转开始)都将被丢弃,并完全替换为从
角度开始的新变换。这就是你看到的“跳跃”


您要做的是将旋转变换应用于图像视图的现有变换。您可以通过调用CGAffineTransformRotate而不是CGAffineTransformMakeRotation来实现这一点。

您可能需要将self.superview更改为self.view(我的是子类)

var xOffSet:CGVector=CGVectorMake(0,0)
变量yOffSet:CGVector=CGVectorMake(0,0)
变量来源:CGPoint=CGPointZero
var TENTERTRANSFORM=CGAFFINTERTRANSFORM()
var启动角度:CGFloat?
覆盖功能触摸开始(触摸:设置,withEvent事件:UIEvent?){
原点=(touch.first?.locationInView(self.superview))!
xOffSet=CGVector(dx:(origin.x)-self.center.x,dy:(origin.y)-self.center.y)
启动角度=atan2(xOffSet.dy,xOffSet.dx)
//保存当前变换
自我转换
}
覆盖功能触摸移动(触摸:设置,带事件:UIEvent?){
让touchPoint=touchs.first?.locationInView(self.superview)
yOffSet=CGVector(dx:touchPoint!.x-self.center.x,dy:touchPoint!.y-self.center.y)
让角度=atan2(yOffSet.dy,yOffSet.dx)
让deltaAngle=角度-开始角度!
self.transform=CGAffineTransformRotate(TELTTransform,deltaAngle)
}
覆盖函数touchesend(touch:Set,withEvent:UIEvent?{
起动角=零
}
//取消拖动时重置
覆盖功能触摸已取消(触摸:设置?,带事件:UIEvent?){
自我变换
起动角=零
}

感谢@matt的回复,我仍然有问题,请参阅updateAnks以获得@Dasem的回复,我仍然有问题,请参阅此部分的更新xOffSet=CGVector(dx:(origin.x)-rotateImageView.center.x,dy:(origin.x)-rotateImageView.center.y)将第二个origin.x更改为origin.y,因此我更新了我的答案(为了清晰起见,还有一些改进)现在可以正常工作了:)我正在尝试使用这段代码做一些类似于这个项目的事情。但是我在将代码翻译成swift 4版本的过程中遇到了一些问题。“我猜”。CGAffineTransform似乎没有“从上一个变换旋转”选项,我不知道如何使用它。我搜索
rotateImageView.transform = CGAffineTransformMakeRotation(angle)
var xOffSet:CGVector = CGVectorMake(0, 0)
var yOffSet:CGVector = CGVectorMake(0, 0)
var origin:CGPoint = CGPointZero
var tempTransform=CGAffineTransform()
var startingAngle:CGFloat?


   override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    origin = (touches.first?.locationInView(self.superview))!
    xOffSet = CGVector(dx:(origin.x)-self.center.x, dy:(origin.y) - self.center.y)
    startingAngle = atan2(xOffSet.dy,xOffSet.dx)

    //save the current transform
    tempTransform = self.transform
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

    let touchPoint = touches.first?.locationInView(self.superview)
    yOffSet = CGVector(dx:touchPoint!.x - self.center.x, dy:touchPoint!.y - self.center.y)
    let angle = atan2(yOffSet.dy,yOffSet.dx)

    let deltaAngle = angle - startingAngle!
    self.transform = CGAffineTransformRotate(tempTransform, deltaAngle) 
}


override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {  
  startingAngle = nil
}

//reset in case drag is cancelled
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
        self.transform = tempTransform
        startingAngle = nil
    }