使用 UIGestureRecognizer 旋转瓶子
Spin bottle with UIGestureRecognizer
我现在正在使用此代码在点击按钮时旋转瓶子:
@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")
}
但是如何使用手势旋转按钮?所以 harder/faster 我移动手指,瓶子旋转得越快
对此的简单回答是...使用 UIScrollView
.
从我这里的问题... Loop UIScrollView but continue decelerating
将它翻译成 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)
}
在这个例子中,我的旋转视图是 arrowView
。 scrollView
和 arrowView
都应该是视图控制器视图的子视图。 scrollView
中不应包含任何内容。
N.B。这是在浏览器中完成的,因此可能存在一些语法问题。您可能还需要将一些数字转换为 CGFloat
等...
此外,能够从 Objective-C 进行翻译对于任何 iOS 开发人员来说都是必不可少的。数百万个应用程序是使用 Objective-C 编写的。语法可能略有不同,但所有 API 都是相同的。
学习如何做到这一点是每个 iOS 开发人员都应该做的事情。
使用UIPanGestureRecognizer
。创建一个 panGestureRecognizer 并将其添加到瓶子的超级视图中并实现它的委托。它有velocityInView
、translationInView
等变量。当用户完成平移时,使用它们来计算旋转的角度、速度和持续时间。
我已经成功地创建了一个示例应用程序,它在中心有一个视图,您可以使用 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)
}
}
}
当您 运行 时,您将能够根据旋转手势的速度旋转视图。
我现在正在使用此代码在点击按钮时旋转瓶子:
@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")
}
但是如何使用手势旋转按钮?所以 harder/faster 我移动手指,瓶子旋转得越快
对此的简单回答是...使用 UIScrollView
.
从我这里的问题... Loop UIScrollView but continue decelerating
将它翻译成 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)
}
在这个例子中,我的旋转视图是 arrowView
。 scrollView
和 arrowView
都应该是视图控制器视图的子视图。 scrollView
中不应包含任何内容。
N.B。这是在浏览器中完成的,因此可能存在一些语法问题。您可能还需要将一些数字转换为 CGFloat
等...
此外,能够从 Objective-C 进行翻译对于任何 iOS 开发人员来说都是必不可少的。数百万个应用程序是使用 Objective-C 编写的。语法可能略有不同,但所有 API 都是相同的。
学习如何做到这一点是每个 iOS 开发人员都应该做的事情。
使用UIPanGestureRecognizer
。创建一个 panGestureRecognizer 并将其添加到瓶子的超级视图中并实现它的委托。它有velocityInView
、translationInView
等变量。当用户完成平移时,使用它们来计算旋转的角度、速度和持续时间。
我已经成功地创建了一个示例应用程序,它在中心有一个视图,您可以使用 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)
}
}
}
当您 运行 时,您将能够根据旋转手势的速度旋转视图。