旋转瓶子与UIGestureRecognizer

12

现在我正在使用这段代码,在按钮点击时旋转瓶子:

@IBAction func spinButton(sender: AnyObject) {
        let rotateView = CABasicAnimation()
        let randonAngle = arc4random_uniform(360) + 720
        rotateView.fromValue = 0
        rotateView.toValue = Float(randonAngle) * Float(M_PI) / 180.0
        rotateView.duration = 3
        rotateView.delegate = self
        rotateView.repeatCount = 0
        rotateView.removedOnCompletion = false
        rotateView.fillMode = kCAFillModeForwards
        rotateView.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
        bottleImageView.layer.addAnimation(rotateView, forKey: "transform.rotation.z")
    }

但是我该如何使用手势旋转按钮?这样我越用力/越快地移动手指,瓶子就会越快地旋转。


1
请问您是否看到了我对答案的编辑。现在它包含了所有的Swift代码,可以实现这个功能。 - Fogmeister
你似乎对此保持沉默了。只是想确认一下,你是否已经解决了它?谢谢。 - Fogmeister
3个回答

2
这个问题的简单答案是...使用 UIScrollView
从我的这个问题开始...循环 UIScrollView 但继续减速 将其翻译成 Swift 很简单,但这里还是给出代码...
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    //make the content size really big so that the targetOffset of the deceleration will never be met.

    scrollView.contentSize = CGSize(width: CGRectGetWidth(scrollView.frame) * 100.0, height: CGRectGetHeight(scrollView.frame))
    //set the contentOffset of the scroll view to a point in the center of the contentSize.
    scrollView.setContentOffset(CGPoint(CGRectGetWidth(scrollView.frame) * 50, 0), animated: false)
}

func rotateImageView() {
    //Calculate the percentage of one "frame" that is the current offset.

    // each percentage of a "frame" equates to a percentage of 2 PI Rads to rotate
    let minOffset = CGRectGetWidth(scrollView.frame) * 50.0
    let maxOffset = CGRectGetWidth(scrollView.frame) * 51.0

    let offsetDiff = maxOffset - minOffset

    let currentOffset = scrollView.contentOffset.x - minOffset

    let percentage = currentOffset / offsetDiff

    arrowView.transform = CGAffineTransformMakeRotation(M_PI * 2 * percentage)
}

func scrollViewDidScroll(scrollView: UIScrollView) {
    //the scrollView moved so update the rotation of the image
    rotateImageView()
}

func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    //the scrollview stopped moving.
    //set the content offset back to be in the middle
    //but make sure to keep the percentage (used above) the same
    //this ensures the arrow is pointing in the same direction as it ended decelerating

    let diffOffset = scrollView.contentOffset.x

    while diffOffset >= CGRectGetWidth(scrollView.frame) {
        diffOffset = diffOffset - CGRectGetWidth(scrollView.frame)
    }

    scrollView.setContentOffset(CGPoint(x: CGRectGetWidth(scrollView.frame) * 50 + diffOffset, y: 0), animated:false)
}

在这个例子中,我的旋转视图是arrowViewscrollViewarrowView都应该是视图控制器的子视图。 scrollView里面不应该有任何内容。

注意:这是在浏览器中完成的,因此可能会出现一些语法问题。您可能还需要将一些数字转换为CGFloat等...

另外,能够从Objective-C进行翻译对于任何iOS开发人员来说都是必不可少的。数百万应用程序都使用Objective-C编写。 语法可能略有不同,但所有API都是相同的。

学习如何做到这一点是每个iOS开发者都应该做的事情。


@RoduckNickes 我找了一下我之前写的代码,但是找不到了。很抱歉。我想那只是我做过的一个实验而已。 - Fogmeister
请问您能否提供一些代码让我可以尝试一下这个旋转瓶子的东西吗? - Roduck Nickes
@Fogmeister 如果您能将其翻译成Swift,那就太棒了 :) - Roduck Nickes
1
@RoduckNickes 完成了。你应该学会如何在 Objective-C 和 Swift 之间进行翻译。这是微不足道但至关重要的。数百万的应用程序和价值数年的教程都是用 Objective-C 编写的。 - Fogmeister
1
@RoduckNickes 我也不建议只是复制粘贴这段代码。这样做你将一无所获,而且很懒散。仔细看看代码,了解它在做什么以及为什么这样做,然后尝试自己重新编写。 - Fogmeister
显示剩余24条评论

2

我已经成功创建了一个示例程序,其中有一个位于中央的视图,您可以使用 UIRotationGestureRecognizer 旋转它,旋转速度将根据旋转速度而受到影响。我使用了 UIDynamics 来实现:

class ViewController: UIViewController {

@IBOutlet weak var sampleView: UIView!

var animator: UIDynamicAnimator?

override func viewDidLoad() {
    super.viewDidLoad()

    setupRotationGesture()

}

override func viewDidAppear(animated: Bool) {

    animator = UIDynamicAnimator(referenceView: self.view)

    let sampleViewBehavior = UIDynamicItemBehavior(items: [self.sampleView])
    sampleViewBehavior.allowsRotation = true // view can rotate
    animator?.addBehavior(sampleViewBehavior)

    let anchoredSuperViewBehavior = UIDynamicItemBehavior(items: [self.view])
    anchoredSuperViewBehavior.anchored = true
    animator?.addBehavior(anchoredSuperViewBehavior)

    // Attachment between the sample view and super view at center anchor point.

    let attachment = UIAttachmentBehavior.pinAttachmentWithItem(self.sampleView, attachedToItem: self.view, attachmentAnchor: CGPointMake(self.view.center.x + 1, self.view.center.y + 1))
    animator?.addBehavior(attachment)
}


// MARK: - Rotation Gesture -

func setupRotationGesture(){

    let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotationGesture(_:)))
    self.sampleView.addGestureRecognizer(rotationGesture)
}

func handleRotationGesture(gesture: UIRotationGestureRecognizer){

    if gesture.state == .Ended {

        let push = UIPushBehavior(items: [self.sampleView], mode: .Instantaneous)

        push.magnitude = abs(50.5 * gesture.velocity)
        let transform = self.sampleView.transform
        push.angle = atan2(transform.b, transform.a);
        animator?.addBehavior(push)
    }

}
 }

当您运行时,您将能够根据旋转手势的速度旋转视图。

1
谢谢,但它只会向右旋转,当我移动手指时它不会移动。我必须使用两个手指,而且它需要很长时间才能停止旋转。有什么想法吗? - Roduck Nickes
1
您可以使用旋转手势中的旋转角度,以便它可以在两个方向上工作。如果您想使用一个手指,您可以使用滑动手势,我认为这很容易。 如果旋转停止时间太长,您可以更改幅度值UIPushBehavior。 我已经给出了整体思路和如何实现。只需要您进行一些微调即可 :) - Hossam Ghareeb

1

使用 UIPanGestureRecognizer。创建一个 panGestureRecognizer 并将其添加到您的瓶子的 superview 中并实现其委托。它有变量,例如 velocityInViewtranslationInView。当用户完成平移时,使用它们来计算旋转的角度、速度和持续时间。


1
@Fogmeister 你设置的 contentSize 是多少?一百万吗?这听起来不对。 - farzadshbfn
1
我是通过将内容大小设置为任意大来实现的。这是为了确保滚动视图永远不会在单个滚动中到达末端。但是,当滚动视图不再滚动时,可以将其重置为0(+-基于角度的偏移量),以便每次旋转停止时都会返回。从而使其具有无限滚动的效果。 - Fogmeister
1
好的,假设你已经解决了它。有一天(比如未来几年),你想要检查一些东西,或者把你的代码交给别人,他读了你的代码,然后就会问:“为什么是scrollView?它在滚动吗?scrollView在哪里?”这就是我的意思。 - farzadshbfn
1
@Fogmeister 嗯,我记得它有一个很大的限制(我想是99k)。但如果到达内容的末尾,你的视图将不再正确地工作(直到你再次将其设置为零)。 - farzadshbfn
1
是的,没错。这就是为什么我说当减速停止时,它应该重置为0(+-基于旋转的内容偏移)。你说得对,如果用户不停地滚动视图,则它最终会停止动画。但是他们需要一段时间才能到达最大偏移量。此外,您可以通过添加一个边缘情况来捕获偏移量(如果太大)并将其再次重置为0来解决这个问题。仍然比使用自定义手势识别器编写所有内容要容易得多。 - Fogmeister
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接