Swift 4 Rotation Jumps Back - ios

I'm rotating a the minute pointer on my watch icon, but at the end of the animation, it jumps back to the starting position. How can I have it stay where it stopped?
let rotation: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotation.toValue = Double.pi
rotation.duration = 0.5 // or however long you want ...
rotation.isCumulative = true
watchIconMin.layer.add(rotation, forKey: "rotationAnimation")

Use UIView animation if watchIconMin is a subclass or class of UIView.
UIView.animate(withDuration: 0.5, animations: {
self.watchIconMin.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
}) { (success) in
self.watchIconMin.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
}

Related

Rotate a view 360 degrees infinitely

I am using this code to rotate a view 360 degrees infinitely. But my view is not rotating:
func rotateImageView() {
UIView.animate(withDuration: 3.0, delay: 0, options: [.repeat, .curveLinear], animations: {
self.vinylView.transform = CGAffineTransform(rotationAngle: .pi * 2)
})
}
How to fix it?
Substitute pi * with /, delete repeat, add completion and recall the function like this:
private func rotateImageView() {
UIView.animate(withDuration: 3, delay: 0, options: .curveLinear, animations: {
self.vinylView.transform = self.vinylView.transform.rotated(by: .pi / 2)
}) { (finished) in
if finished {
self.rotateImageView()
}
}
}
Solution using CABasicAnimation
// Rotate vinvlView
vinylView.layer.add(CABasicAnimation.rotation, forKey: nil)
extension CABasicAnimation {
static let rotation : CABasicAnimation = {
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
animation.repeatCount = .infinity // Rotate a view 360 degrees infinitely
animation.fromValue = 0
animation.toValue = CGFloat.pi * 2
animation.duration = 3.0
return animation
}()
}

Multiple Animations For Same UIView in Swift

I am trying to add multiple animations for my image view, but only one of them is animated. Please check the below code. I created scale and rotate animations for my image view but only i see the scale animation when run the below code.
//Rotate animation
let rotation: CABasicAnimation = CABasicAnimation(keyPath:
"transform.rotation.y")
rotation.toValue = 0
rotation.fromValue = 2.61
//Scale animation
let scale: CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")
scale.toValue = 1
scale.fromValue = 0
//Adding animations to group
let group = CAAnimationGroup()
group.animations = [rotation,scale]
group.duration = 0.2
myImage.layer.add(group, forKey: nil)
The rotation occurs but the duration is less to notice
group.duration = 0.2
when changed to 5 seconds see
in your completion you can put your animations, when finish one, wait second.. and etc
let myImage = UIImageView()
UIView.animate(withDuration: 1.0, animations: {
let rotation: CABasicAnimation = CABasicAnimation(keyPath:
"transform.rotation.y")
rotation.toValue = 0
rotation.fromValue = 2.61
}, completion: { (value: Bool) in
UIView.animate(withDuration: 1.0, animations: {
//you can here put your other animation
})
})

Problems rotating view

I want to animate a UIImageView. The image should only spin clockwise. When the image is spinning, I want to speed it up. When I do speed it up, it goes counterclockwise and the start position is not correct as well. This is my code:
func rotateAnimation(theView: UIView, duration: CFTimeInterval = 2.0, repeatCount: Float = 1, toValue: CGFloat = CGFloat(.pi * 2.0), linear: Bool = false, animation: String = "transform.rotation") {
let rotateAnimation = CABasicAnimation(keyPath: animation)
let currentLayer = (theView.layer.presentation())
var currentAngle = CFloat((currentLayer?.value(forKeyPath: "transform.rotation") as? NSNumber)!)
currentAngle = roundf(currentAngle * 180 / Float(Double.pi))
print(currentAngle)
rotateAnimation.fromValue = currentAngle
if !linear{
rotateAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
}
rotateAnimation.toValue = toValue
rotateAnimation.duration = duration
rotateAnimation.repeatCount = repeatCount
theView.layer.add(rotateAnimation, forKey: nil)
}
The print shows me to correct angle.
I am calling this method below twice. The second time I am calling it, the image is spinning counterclock:
rotateAnimation(theView: star, duration: 15.0, repeatCount: Float.infinity, toValue: CGFloat(Double.pi * 2), linear: true)
delay(delay: 3.5, closure: {
self.rotateAnimation(theView: self.star, duration: 7, repeatCount: Float.infinity, toValue: CGFloat(Double.pi * 2), linear: true)
})

iOS animating object goes back to original position

I am trying to animate the position of a UIView object with CABasicAnimation on a button Tap. The object animated and moves to the 'to' position, but returns back to the original position after the animation ends. I want to retain the position of the view object even after the animation ends. This the code snippet that performs the animation. viewObject is the object which I'm trying to animate.
let animation = CABasicAnimation(keyPath: "position")
animation.timingFunction = CAMediaTimingFunction(controlPoints: 0.86, 0, 0.07, 1.0)
animation.duration = 0.5
animation.fromValue = NSValue(cgPoint: CGPoint(x: viewObject.center.x, y: viewObject.center.y))
animation.toValue = NSValue(cgPoint: CGPoint(x: viewObject.center.x + 64, y: viewObject.center.y))
viewObject.layer.add(animation, forKey: "position")
add following lines before adding animation
animation.isRemovedOnCompletion = false
animation.fillMode = kCAFillModeForwards
Swift
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
Please add the following code:
Objective-C:
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
Swift 4:
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
I think you need to give frame again on completion. So, this can be a nice approach
UIView.animate(withDuration: 0.7, delay: 1.0, options: .curveLinear, animations: {
let animation = CABasicAnimation(keyPath: "position")
animation.timingFunction = CAMediaTimingFunction(controlPoints: 0.86, 0, 0.07, 1.0)
animation.duration = 0.5
animation.fromValue = NSValue(cgPoint: CGPoint(x: self.viewObject.center.x, y: self.viewObject.center.y))
animation.toValue = NSValue(cgPoint: CGPoint(x: self.viewObject.center.x + 64, y: self.viewObject.center.y))
self.viewObject.layer.add(animation, forKey: "position")
}, completion: { finished in
self.viewObject.frame.origin.x = self.viewObject.frame.origin.x + 64
})
Try this. It will work perfectly
UIView.animateWithDuration(0.7, delay: 1.0, options: .CurveEaseOut, animations:
{
Code
}, completion:
{
finished in
println("Nothing to do!")
})
Just do animation inside a block and when it finishes. hold that position and do not revert back. It should stay at same position
and add this line inside code
cabasicanimation.removedOnCompletion = false;
This line will make it do not go back in the same state
If you want keep your position, you should put your code same my structure
CATransaction.begin()
CATransaction.setDisableActions(true)
CATransaction.setCompletionBlock {
// Input code set new position at here
}
// Intput code animation
CATransaction.commit()

How to control animation rotation direction in Swift past 180º?

According to the documentation for rotated(by:):
angle
The angle, in radians, by which to rotate the affine transform. In iOS, a positive value specifies counterclockwise rotation and a negative value specifies clockwise rotation.
This has caused much confusion and has been partly answered, but even if we accept that the coordinate system is flipped (and just do the opposite of what the documentation says), it still provides inconsistent results when animating.
The direction of rotation -- clockwise or counterclockwise -- depends on the proximity of the target rotation to the current rotation:
<= 180º animates clockwise
> 180º animates counter-clockwise
Using UIView.animate or UIViewPropertyAnimator shows the inconsistency:
// Animates CLOCKWISE
UIView.animate(withDuration: 2.0) {
let radians = Angle(179).radians // 3.12413936106985
view.transform = view.transform.rotated(by: CGFloat(radians))
}
// Animates COUNTER-CLOCKWISE
UIViewPropertyAnimator(duration: 2, curve: .linear) {
let radians = Angle(181).radians // 3.15904594610974
view.transform = view.transform.rotated(by: CGFloat(radians))
}
// Does not animate
UIViewPropertyAnimator(duration: 2, curve: .linear) {
let radians = Angle(360).radians // 6.28318530717959
view.transform = view.transform.rotated(by: CGFloat(radians))
}
Try this:
let multiplier: Double = isSelected ? 1 : -2
let angle = CGFloat(multiplier * Double.pi)
UIView.animate(withDuration: 0.4) {
self.indicatorImageView.transform = CGAffineTransform(rotationAngle: angle)
}
The answer is to use CABasicAnimation for rotations past 180º, keeping in mind that positive values are clockwise and negative values are counterclockwise.
// Rotate 360º clockwise.
let rotate = CABasicAnimation(keyPath: "transform.rotation")
rotate.fromValue = Angle(0).radians
rotate.toValue = Angle(360).radians
rotate.duration = 2.0
self.layer.add(rotate, forKey: "transform.rotation")
if sender.isSelected {
/// clockwise
let rotate = CABasicAnimation(keyPath: "transform.rotation")
rotate.fromValue = 0
rotate.toValue = CGFloat.pi
rotate.duration = 0.25
rotate.fillMode = CAMediaTimingFillMode.forwards
rotate.isRemovedOnCompletion = false
self.arrowButton.layer.add(rotate, forKey: "transform.rotation")
} else {
/// anticlockwise
let rotate = CABasicAnimation(keyPath: "transform.rotation")
rotate.fromValue = CGFloat.pi
rotate.toValue = 0
rotate.duration = 0.25
rotate.fillMode = CAMediaTimingFillMode.forwards
rotate.isRemovedOnCompletion = false
self.arrowButton.layer.add(rotate, forKey: "transform.rotation")
}
The third option allows you to rotate over 180º in the desired direction:
// #1 This rotates 90º clockwise
UIView.animate(withDuration: 0.25, animations:{
view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi/2)
})
// #2 This rotates 90º counter clockwise back to #1
UIView.animate(withDuration: 0.25, animations:{
view.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
})
// #3 This rotates 270º clockwise back to #1
UIView.animate(withDuration: 0.1875, animations:{
view.transform = CGAffineTransform(rotationAngle: CGFloat.pi/2)
}, completion: { _ in
UIView.animate(withDuration: 0.0625, animations:{
view.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
})
})

Resources