[英]UIView Infinite 360 degree rotation animation?
我正在嘗試將UIImageView
旋轉 360 度,並在線查看了幾個教程。 如果UIView
不停止或跳轉到新的 position,我無法讓它們工作。
我嘗試過的最新的事情是:
[UIView animateWithDuration:1.0
delay:0.0
options:0
animations:^{
imageToMove.transform = CGAffineTransformMakeRotation(M_PI);
}
completion:^(BOOL finished){
NSLog(@"Done!");
}];
但是如果我使用 2*pi,它根本不會移動(因為它是相同的位置)。 如果我嘗試只執行 pi(180 度),它會起作用,但如果我再次調用該方法,它會向后旋轉。
編輯:
[UIView animateWithDuration:1.0
delay:0.0
options:0
animations:^{
[UIView setAnimationRepeatCount:HUGE_VALF];
[UIView setAnimationBeginsFromCurrentState:YES];
imageToMove.transform = CGAffineTransformMakeRotation(M_PI);
}
completion:^(BOOL finished){
NSLog(@"Done!");
}];
也不起作用。 它達到180
度,暫停一秒鍾,然后在再次開始之前重置回0
度。
找到了一個非常適合我的方法(我稍微修改了一下): iphone UIImageView rotation
#import <QuartzCore/QuartzCore.h>
- (void) runSpinAnimationOnView:(UIView*)view duration:(CGFloat)duration rotations:(CGFloat)rotations repeat:(float)repeat {
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = repeat ? HUGE_VALF : 0;
[view.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}
感謝 Richard J. Ross III 提出的想法,但我發現他的代碼並不是我所需要的。 我相信options
的默認設置是為您提供UIViewAnimationOptionCurveEaseInOut
,這在連續動畫中看起來不正確。 此外,我添加了一個檢查,以便我可以在需要時在偶數四分之一圈停止動畫(不是無限,而是無限期),並在前 90 度期間加速加速,並在最后 90 度減速(請求停止后):
// an ivar for your class:
BOOL animating;
- (void)spinWithOptions:(UIViewAnimationOptions)options {
// this spin completes 360 degrees every 2 seconds
[UIView animateWithDuration:0.5
delay:0
options:options
animations:^{
self.imageToMove.transform = CGAffineTransformRotate(imageToMove.transform, M_PI / 2);
}
completion:^(BOOL finished) {
if (finished) {
if (animating) {
// if flag still set, keep spinning with constant speed
[self spinWithOptions: UIViewAnimationOptionCurveLinear];
} else if (options != UIViewAnimationOptionCurveEaseOut) {
// one last spin, with deceleration
[self spinWithOptions: UIViewAnimationOptionCurveEaseOut];
}
}
}];
}
- (void)startSpin {
if (!animating) {
animating = YES;
[self spinWithOptions: UIViewAnimationOptionCurveEaseIn];
}
}
- (void)stopSpin {
// set the flag to stop spinning after one last 90 degree increment
animating = NO;
}
我添加了處理請求以再次開始旋轉 ( startSpin
) 的功能,而之前的旋轉正在結束(完成)。 Github 上的示例項目。
在 Swift 中,您可以使用以下代碼進行無限旋轉:
extension UIView {
private static let kRotationAnimationKey = "rotationanimationkey"
func rotate(duration: Double = 1) {
if layer.animation(forKey: UIView.kRotationAnimationKey) == nil {
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotationAnimation.fromValue = 0.0
rotationAnimation.toValue = Float.pi * 2.0
rotationAnimation.duration = duration
rotationAnimation.repeatCount = Float.infinity
layer.add(rotationAnimation, forKey: UIView.kRotationAnimationKey)
}
}
func stopRotating() {
if layer.animation(forKey: UIView.kRotationAnimationKey) != nil {
layer.removeAnimation(forKey: UIView.kRotationAnimationKey)
}
}
}
let kRotationAnimationKey = "com.myapplication.rotationanimationkey" // Any key
func rotateView(view: UIView, duration: Double = 1) {
if view.layer.animationForKey(kRotationAnimationKey) == nil {
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotationAnimation.fromValue = 0.0
rotationAnimation.toValue = Float(M_PI * 2.0)
rotationAnimation.duration = duration
rotationAnimation.repeatCount = Float.infinity
view.layer.addAnimation(rotationAnimation, forKey: kRotationAnimationKey)
}
}
停止就像:
func stopRotatingView(view: UIView) {
if view.layer.animationForKey(kRotationAnimationKey) != nil {
view.layer.removeAnimationForKey(kRotationAnimationKey)
}
}
上面 Nate 的回答非常適合停止和開始動畫,並提供更好的控制。 我很好奇為什么你的不起作用而他的起作用。 我想在這里分享我的發現和一個更簡單的代碼版本,它可以連續地為 UIView 設置動畫而不會停頓。
這是我使用的代碼,
- (void)rotateImageView
{
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[self.imageView setTransform:CGAffineTransformRotate(self.imageView.transform, M_PI_2)];
}completion:^(BOOL finished){
if (finished) {
[self rotateImageView];
}
}];
}
我使用了“CGAffineTransformRotate”而不是“CGAffineTransformMakeRotation”,因為前者返回的結果隨着動畫的進行而保存。 這將防止在動畫期間跳轉或重置視圖。
另一件事是不要使用“UIViewAnimationOptionRepeat”,因為在動畫開始重復之前,它會在動畫結束時重置變換,使視圖跳回其原始位置。 不是重復,而是遞歸,以便變換永遠不會重置為原始值,因為動畫塊幾乎永遠不會結束。
最后一件事是,您必須以 90 度 (M_PI / 2) 而不是 360 或 180 度(2*M_PI 或 M_PI)的步長轉換視圖。 因為變換是作為正弦值和余弦值的矩陣乘法發生的。
t' = [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] * t
因此,假設您使用 180 度變換,則 180 的余弦產生 -1,每次都使視圖沿相反方向進行變換(如果將變換的弧度值更改為 M_PI,Note-Nate 的回答也會出現此問題)。 360 度變換只是要求視圖保持原樣,因此您根本看不到任何旋轉。
我對來自已檢查解決方案的 Swift 擴展的貢獻:
斯威夫特 4.0
extension UIView{
func rotate() {
let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotation.toValue = NSNumber(value: Double.pi * 2)
rotation.duration = 1
rotation.isCumulative = true
rotation.repeatCount = Float.greatestFiniteMagnitude
self.layer.add(rotation, forKey: "rotationAnimation")
}
}
已棄用:
extension UIView{
func rotate() {
let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotation.toValue = NSNumber(double: M_PI * 2)
rotation.duration = 1
rotation.cumulative = true
rotation.repeatCount = FLT_MAX
self.layer.addAnimation(rotation, forKey: "rotationAnimation")
}
}
如果你想做的只是無休止地旋轉圖像,這很有效,而且非常簡單:
NSTimeInterval duration = 10.0f;
CGFloat angle = M_PI / 2.0f;
CGAffineTransform rotateTransform = CGAffineTransformRotate(imageView.transform, angle);
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionRepeat| UIViewAnimationOptionCurveLinear animations:^{
imageView.transform = rotateTransform;
} completion:nil];
根據我的經驗,這可以完美地工作,但請確保您的圖像能夠圍繞其中心旋轉而沒有任何偏移,否則圖像動畫一旦轉到 PI 就會“跳躍”。
要更改旋轉方向,請更改angle
的符號 ( angle *= -1
)。
@AlexPretzlav 的更新評論讓我重新審視了這個,我意識到當我寫這篇文章時,我旋轉的圖像是沿垂直和水平軸鏡像的,這意味着圖像確實只旋轉了 90 度然后重新設置,雖然它看起來像它一直在不停地旋轉。
所以,如果你的圖像和我的一樣,這會很好用,但是,如果圖像不對稱,你會注意到在 90 度后“快速”回到原始方向。
要旋轉非對稱圖像,最好使用已接受的答案。
如下所示,這些不太優雅的解決方案之一將真正旋轉圖像,但在重新啟動動畫時可能會出現明顯的卡頓:
- (void)spin
{
NSTimeInterval duration = 0.5f;
CGFloat angle = M_PI_2;
CGAffineTransform rotateTransform = CGAffineTransformRotate(self.imageView.transform, angle);
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.imageView.transform = rotateTransform;
} completion:^(BOOL finished) {
[self spin];
}];
}
正如@richard-j-ross-iii 所建議的那樣,您也可以僅使用塊來執行此操作,但是由於塊正在捕獲自身,因此您將收到保留循環警告:
__block void(^spin)() = ^{
NSTimeInterval duration = 0.5f;
CGFloat angle = M_PI_2;
CGAffineTransform rotateTransform = CGAffineTransformRotate(self.imageView.transform, angle);
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.imageView.transform = rotateTransform;
} completion:^(BOOL finished) {
spin();
}];
};
spin();
David Rysanek 的精彩回答更新到Swift 4 :
import UIKit
extension UIView {
func startRotating(duration: CFTimeInterval = 3, repeatCount: Float = Float.infinity, clockwise: Bool = true) {
if self.layer.animation(forKey: "transform.rotation.z") != nil {
return
}
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
let direction = clockwise ? 1.0 : -1.0
animation.toValue = NSNumber(value: .pi * 2 * direction)
animation.duration = duration
animation.isCumulative = true
animation.repeatCount = repeatCount
self.layer.add(animation, forKey:"transform.rotation.z")
}
func stopRotating() {
self.layer.removeAnimation(forKey: "transform.rotation.z")
}
}
}
這對我有用:
[UIView animateWithDuration:1.0
animations:^
{
self.imageView.transform = CGAffineTransformMakeRotation(M_PI);
self.imageView.transform = CGAffineTransformMakeRotation(0);
}];
這是我作為 UIView 擴展的快速解決方案。 它可以被視為對任何 UIImageView 上的 UIActivityIndicator 行為的模擬。
import UIKit
extension UIView
{
/**
Starts rotating the view around Z axis.
@param duration Duration of one full 360 degrees rotation. One second is default.
@param repeatCount How many times the spin should be done. If not provided, the view will spin forever.
@param clockwise Direction of the rotation. Default is clockwise (true).
*/
func startZRotation(duration duration: CFTimeInterval = 1, repeatCount: Float = Float.infinity, clockwise: Bool = true)
{
if self.layer.animationForKey("transform.rotation.z") != nil {
return
}
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
let direction = clockwise ? 1.0 : -1.0
animation.toValue = NSNumber(double: M_PI * 2 * direction)
animation.duration = duration
animation.cumulative = true
animation.repeatCount = repeatCount
self.layer.addAnimation(animation, forKey:"transform.rotation.z")
}
/// Stop rotating the view around Z axis.
func stopZRotation()
{
self.layer.removeAnimationForKey("transform.rotation.z")
}
}
我在這個存儲庫中找到了不錯的代碼,
這是它的代碼,我根據我對速度的需要做了一些小的改動:)
UIImageView+Rotate.h
#import <Foundation/Foundation.h>
@interface UIImageView (Rotate)
- (void)rotate360WithDuration:(CGFloat)duration repeatCount:(float)repeatCount;
- (void)pauseAnimations;
- (void)resumeAnimations;
- (void)stopAllAnimations;
@end
UIImageView+Rotate.m
#import <QuartzCore/QuartzCore.h>
#import "UIImageView+Rotate.h"
@implementation UIImageView (Rotate)
- (void)rotate360WithDuration:(CGFloat)duration repeatCount:(float)repeatCount
{
CABasicAnimation *fullRotation;
fullRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
fullRotation.fromValue = [NSNumber numberWithFloat:0];
//fullRotation.toValue = [NSNumber numberWithFloat:(2*M_PI)];
fullRotation.toValue = [NSNumber numberWithFloat:-(2*M_PI)]; // added this minus sign as i want to rotate it to anticlockwise
fullRotation.duration = duration;
fullRotation.speed = 2.0f; // Changed rotation speed
if (repeatCount == 0)
fullRotation.repeatCount = MAXFLOAT;
else
fullRotation.repeatCount = repeatCount;
[self.layer addAnimation:fullRotation forKey:@"360"];
}
//Not using this methods :)
- (void)stopAllAnimations
{
[self.layer removeAllAnimations];
};
- (void)pauseAnimations
{
[self pauseLayer:self.layer];
}
- (void)resumeAnimations
{
[self resumeLayer:self.layer];
}
- (void)pauseLayer:(CALayer *)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
- (void)resumeLayer:(CALayer *)layer
{
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
@end
Swift3 版本:
extension UIView {
func startRotate() {
let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotation.fromValue = 0
rotation.toValue = NSNumber(value: M_PI * 2)
rotation.duration = 2
rotation.isCumulative = true
rotation.repeatCount = FLT_MAX
self.layer.add(rotation, forKey: "rotationAnimation")
}
func stopRotate() {
self.layer.removeAnimation(forKey: "rotationAnimation")
}
}
並記住在viewWillAppear
中調用startRotate
而不是在viewDidLoad
。
使用四分之一圈,並逐漸增加圈數。
void (^block)() = ^{
imageToMove.transform = CGAffineTransformRotate(imageToMove.transform, M_PI / 2);
}
void (^completion)(BOOL) = ^(BOOL finished){
[UIView animateWithDuration:1.0
delay:0.0
options:0
animations:block
completion:completion];
}
completion(YES);
@ram 的回答真的很有幫助。 這是答案的 Swift 版本。
斯威夫特 2
private func rotateImageView() {
UIView.animateWithDuration(1, delay: 0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, CGFloat(M_PI_2))
}) { (finished) -> Void in
if finished {
self.rotateImageView()
}
}
}
斯威夫特 3,4,5
private func rotateImageView() {
UIView.animate(withDuration: 1, delay: 0, options: UIView.AnimationOptions.curveLinear, animations: { () -> Void in
self.imageView.transform = self.imageView.transform.rotated(by: .pi / 2)
}) { (finished) -> Void in
if finished {
self.rotateImageView()
}
}
}
您還可以使用 UIView 和塊來制作相同類型的動畫。 這是一個可以任意角度旋轉視圖的類擴展方法。
- (void)rotationWithDuration:(NSTimeInterval)duration angle:(CGFloat)angle options:(UIViewAnimationOptions)options
{
// Repeat a quarter rotation as many times as needed to complete the full rotation
CGFloat sign = angle > 0 ? 1 : -1;
__block NSUInteger numberRepeats = floorf(fabsf(angle) / M_PI_2);
CGFloat quarterDuration = duration * M_PI_2 / fabs(angle);
CGFloat lastRotation = angle - sign * numberRepeats * M_PI_2;
CGFloat lastDuration = duration - quarterDuration * numberRepeats;
__block UIViewAnimationOptions startOptions = UIViewAnimationOptionBeginFromCurrentState;
UIViewAnimationOptions endOptions = UIViewAnimationOptionBeginFromCurrentState;
if (options & UIViewAnimationOptionCurveEaseIn || options == UIViewAnimationOptionCurveEaseInOut) {
startOptions |= UIViewAnimationOptionCurveEaseIn;
} else {
startOptions |= UIViewAnimationOptionCurveLinear;
}
if (options & UIViewAnimationOptionCurveEaseOut || options == UIViewAnimationOptionCurveEaseInOut) {
endOptions |= UIViewAnimationOptionCurveEaseOut;
} else {
endOptions |= UIViewAnimationOptionCurveLinear;
}
void (^lastRotationBlock)(void) = ^ {
[UIView animateWithDuration:lastDuration
delay:0
options:endOptions
animations:^{
self.transform = CGAffineTransformRotate(self.transform, lastRotation);
}
completion:^(BOOL finished) {
NSLog(@"Animation completed");
}
];
};
if (numberRepeats) {
__block void (^quarterSpinningBlock)(void) = ^{
[UIView animateWithDuration:quarterDuration
delay:0
options:startOptions
animations:^{
self.transform = CGAffineTransformRotate(self.transform, M_PI_2);
numberRepeats--;
}
completion:^(BOOL finished) {
if (numberRepeats > 0) {
startOptions = UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveLinear;
quarterSpinningBlock();
} else {
lastRotationBlock();
}NSLog(@"Animation completed");
}
];
};
quarterSpinningBlock();
} else {
lastRotationBlock();
}
}
如果有人想要 nates 的解決方案但很快,那么這里是一個粗略的快速翻譯:
class SomeClass: UIViewController {
var animating : Bool = false
@IBOutlet weak var activityIndicatorImage: UIImageView!
func startSpinning() {
if(!animating) {
animating = true;
spinWithOptions(UIViewAnimationOptions.CurveEaseIn);
}
}
func stopSpinning() {
animating = false
}
func spinWithOptions(options: UIViewAnimationOptions) {
UIView.animateWithDuration(0.5, delay: 0.0, options: options, animations: { () -> Void in
let val : CGFloat = CGFloat((M_PI / Double(2.0)));
self.activityIndicatorImage.transform = CGAffineTransformRotate(self.activityIndicatorImage.transform,val)
}) { (finished: Bool) -> Void in
if(finished) {
if(self.animating){
self.spinWithOptions(UIViewAnimationOptions.CurveLinear)
} else if (options != UIViewAnimationOptions.CurveEaseOut) {
self.spinWithOptions(UIViewAnimationOptions.CurveEaseOut)
}
}
}
}
override func viewDidLoad() {
startSpinning()
}
}
對於 xamarin ios:
public static void RotateAnimation (this UIView view, float duration=1, float rotations=1, float repeat=int.MaxValue)
{
var rotationAnimation = CABasicAnimation.FromKeyPath ("transform.rotation.z");
rotationAnimation.To = new NSNumber (Math.PI * 2.0 /* full rotation*/ * 1 * 1);
rotationAnimation.Duration = 1;
rotationAnimation.Cumulative = true;
rotationAnimation.RepeatCount = int.MaxValue;
rotationAnimation.RemovedOnCompletion = false;
view.Layer.AddAnimation (rotationAnimation, "rotationAnimation");
}
這就是我向正確方向旋轉 360 度的方式。
[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionRepeat|UIViewAnimationOptionCurveLinear
animations:^{
[imageIndView setTransform:CGAffineTransformRotate([imageIndView transform], M_PI-0.00001f)];
} completion:nil];
創建動畫
- (CABasicAnimation *)spinAnimationWithDuration:(CGFloat)duration clockwise:(BOOL)clockwise repeat:(BOOL)repeats
{
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
anim.toValue = clockwise ? @(M_PI * 2.0) : @(M_PI * -2.0);
anim.duration = duration;
anim.cumulative = YES;
anim.repeatCount = repeats ? CGFLOAT_MAX : 0;
return anim;
}
將其添加到這樣的視圖中
CABasicAnimation *animation = [self spinAnimationWithDuration:1.0 clockwise:YES repeat:YES];
[self.spinningView.layer addAnimation:animation forKey:@"rotationAnimation"];
這個答案有什么不同? 如果您的大多數函數都返回對象,而不是只是到處操作一些對象,那么您將擁有更清晰的代碼。
使用 UIView 執行 360 度動畫有以下不同的方法。
使用CABasicAnimation
var rotationAnimation = CABasicAnimation()
rotationAnimation = CABasicAnimation.init(keyPath: "transform.rotation.z")
rotationAnimation.toValue = NSNumber(value: (Double.pi))
rotationAnimation.duration = 1.0
rotationAnimation.isCumulative = true
rotationAnimation.repeatCount = 100.0
view.layer.add(rotationAnimation, forKey: "rotationAnimation")
這是處理開始和停止旋轉操作的 UIView 的擴展函數:
extension UIView {
// Start rotation
func startRotation() {
let rotation = CABasicAnimation(keyPath: "transform.rotation.z")
rotation.fromValue = 0
rotation.toValue = NSNumber(value: Double.pi)
rotation.duration = 1.0
rotation.isCumulative = true
rotation.repeatCount = FLT_MAX
self.layer.add(rotation, forKey: "rotationAnimation")
}
// Stop rotation
func stopRotation() {
self.layer.removeAnimation(forKey: "rotationAnimation")
}
}
現在使用UIView.animation閉包:
UIView.animate(withDuration: 0.5, animations: {
view.transform = CGAffineTransform(rotationAngle: (CGFloat(Double.pi))
}) { (isAnimationComplete) in
// Animation completed
}
我開發了一個閃亮的動畫框架,可以節省你的時間! 使用它可以很容易地創建這個動畫:
private var endlessRotater: EndlessAnimator!
override func viewDidAppear(animated: Bool)
{
super.viewDidAppear(animated)
let rotationAnimation = AdditiveRotateAnimator(M_PI).to(targetView).duration(2.0).baseAnimation(.CurveLinear)
endlessRotater = EndlessAnimator(rotationAnimation)
endlessRotater.animate()
}
要停止此動畫,只需將nil
設置為endlessRotater
。
有興趣的可以看看: https : //github.com/hip4yes/Animatics
斯威夫特 4 ,
func rotateImage(image: UIImageView) {
UIView.animate(withDuration: 1, animations: {
image.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
image.transform = CGAffineTransform.identity
}) { (completed) in
self.rotateImage()
}
}
斯威夫特 4.0
func rotateImageView()
{
UIView.animate(withDuration: 0.3, delay: 0, options: .curveLinear, animations: {() -> Void in
self.imageView.transform = self.imageView.transform.rotated(by: .pi / 2)
}, completion: {(_ finished: Bool) -> Void in
if finished {
rotateImageView()
}
})
}
使用關鍵幀動畫的 Swift 5 UIView 擴展
這種方式允許我們直接使用 UIView.AnimationOptions.repeat
public extension UIView {
func animateRotation(duration: TimeInterval, repeat: Bool, completion: ((Bool) -> ())?) {
var options = UIView.KeyframeAnimationOptions(rawValue: UIView.AnimationOptions.curveLinear.rawValue)
if `repeat` {
options.insert(.repeat)
}
UIView.animateKeyframes(withDuration: duration, delay: 0, options: options, animations: {
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.25, animations: {
self.transform = CGAffineTransform(rotationAngle: CGFloat.pi/2)
})
UIView.addKeyframe(withRelativeStartTime: 0.25, relativeDuration: 0.25, animations: {
self.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
})
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.25, animations: {
self.transform = CGAffineTransform(rotationAngle: 3*CGFloat.pi/2)
})
UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 0.25, animations: {
self.transform = CGAffineTransform(rotationAngle: 2*CGFloat.pi)
})
}, completion: completion)
}
}
斯威夫特:
func runSpinAnimationOnView(view:UIView , duration:Float, rotations:Double, repeatt:Float ) ->()
{
let rotationAnimation=CABasicAnimation();
rotationAnimation.keyPath="transform.rotation.z"
let toValue = M_PI * 2.0 * rotations ;
// passing it a float
let someInterval = CFTimeInterval(duration)
rotationAnimation.toValue=toValue;
rotationAnimation.duration=someInterval;
rotationAnimation.cumulative=true;
rotationAnimation.repeatCount=repeatt;
view.layer.addAnimation(rotationAnimation, forKey: "rotationAnimation")
}
斯威夫特3:
var rotationAnimation = CABasicAnimation()
rotationAnimation = CABasicAnimation.init(keyPath: "transform.rotation.z")
rotationAnimation.toValue = NSNumber(value: (M_PI * 2.0))
rotationAnimation.duration = 2.0
rotationAnimation.isCumulative = true
rotationAnimation.repeatCount = 10.0
view.layer.add(rotationAnimation, forKey: "rotationAnimation")
let val = CGFloat(M_PI_2)
UIView.animate(withDuration: 1, delay: 0, options: [.repeat, .curveLinear], animations: {
self.viewToRotate.transform = self.viewToRotate.transform.rotated(by: val)
})
import UIKit
class RotatingImageView: UIImageView, CAAnimationDelegate {
private let rotationAnimationKey = "rotationAnimationKey"
private var shouldStopRotating = false
func startRotating(witFullRotationDuration duration: Double = 0.5, halfRotation: Bool = true) {
shouldStopRotating = false
if layer.animation(forKey: rotationAnimationKey) == nil {
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotationAnimation.fromValue = 0.0
rotationAnimation.toValue = halfRotation ? Float.pi : Float.pi * 2
rotationAnimation.duration = duration
rotationAnimation.repeatCount = 1
rotationAnimation.delegate = self
layer.add(rotationAnimation, forKey: rotationAnimationKey)
}
}
func stopRotating(immediately: Bool = false) {
if immediately {
if layer.animation(forKey: rotationAnimationKey) != nil {
layer.removeAnimation(forKey: rotationAnimationKey)
}
} else {
shouldStopRotating = true
}
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if !shouldStopRotating {
startRotating(witFullRotationDuration: anim.duration)
} else {
if layer.animation(forKey: rotationAnimationKey) != nil {
layer.removeAnimation(forKey: rotationAnimationKey)
}
}
}
}
我認為你最好添加一個UIVIew
類別:
#import <QuartzCore/QuartzCore.h>
#import "UIView+Rotate.h"
(void)remrotate360WithDuration:(CGFloat)duration repeatCount: (float)repeatCount { CABasicAnimation *fullRotation; fullRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"]; fullRotation.fromValue = [NSNumber numberWithFloat:0]; fullRotation.toValue = [NSNumber numberWithFloat:(2*M_PI)]; // fullRotation.toValue = [NSNumber numberWithFloat:-(2*M_PI)]; // added this minus sign as i want to rotate it to anticlockwise fullRotation.duration = duration; fullRotation.speed = 2.0f; // Changed rotation speed if (repeatCount == 0) fullRotation.repeatCount = MAXFLOAT; else fullRotation.repeatCount = repeatCount; [self.layer addAnimation:fullRotation forKey:@"360"]; }
(void)remstopAllAnimations { [self.layer removeAllAnimations]; };
(void)rempauseAnimations { [self rempauseLayer:self.layer]; }
(void)remresumeAnimations { [self remresumeLayer:self.layer]; }
(void)rempauseLayer:(CALayer *)layer { CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; layer.speed = 0.0; layer.timeOffset = pausedTime; }
(void)remresumeLayer:(CALayer *)layer { CFTimeInterval pausedTime = [layer timeOffset]; layer.speed = 1.0; layer.timeOffset = 0.0; layer.beginTime = 0.0; CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; layer.beginTime = timeSincePause; }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.