iOS 動畫

####UIView 之animation s = vt; 這個是我對動畫的理解, 任何動畫均可以用這個來解釋分析。 咱們設置一個動畫 每每是限定了 運動變化(軌跡)和時間,最多見的是 app

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.30];//時間
[UIView setAnimationDelegate:self];
self.transform = rotationTransform;//視圖改變
[UIView commitAnimations];

或者oop

[UIView animateWithDuration:0.3 animations:^{
       
        }];
```        
UIView animateWithDuration:… 這個方法 apple也作了不少的擴展,對一些簡單的單一需求也能知足。
這邊對下面這個帶有阻尼效果的動畫作個簡單分析

+ (void)animateWithDuration:(NSTimeInterval)duration                      delay:(NSTimeInterval)delay     usingSpringWithDamping:(CGFloat)dampingRatio      initialSpringVelocity:(CGFloat)velocity                    options:(UIViewAnimationOptions)options                 animations:(void (^)(void))animations                  completion:(void (^)(BOOL finished))completion動畫

usingSpringWithDamping(阻尼係數)
的範圍爲0.0f
到1.0f
,數值越小「彈簧」的振動效果越明顯。initialSpringVelocity(初始運動速度),數值越大一開始移動速度越快。

UIView還有一種在實際開發過程當中比較常見的轉場動畫:
  • (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion
如自定義拍照或錄製視頻功能時,在點擊先後攝像頭圖標 視圖內的畫面旋轉天然切換,圖片集瀏覽。

UIViewAnimationOptions:
    UIViewAnimationOptionTransitionNone            = 0 << 20, //default
    UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20,  
    UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20,
    UIViewAnimationOptionTransitionCurlUp          = 3 << 20,
    UIViewAnimationOptionTransitionCurlDown        = 4 << 20,
    UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20,
    UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20,
    UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20,


####UILayer之CAAnimation

@interface CAAnimation : NSObject <NSCoding, NSCopying, CAMediaTiming, CAAction>url

從上看出CAAnimation 使用了CAMediaTiming協議,能夠設置動畫的開始時間、持續時間、速度、重複次數等,使用了CAAction協議,能夠設置動畫的方式(路徑)來顯示動畫。
 CAAnimation 設置動畫原理和UIView差很少,CAAnimation是做用於Layer層上的,而UIView animation 是做用於View上的。 
CAAnimation的一些派生類:
     CATransition 提供漸變效果:(推拉push效果,消退fade效果,揭開reveal效果)
     CAAnimationGroup 容許多個動畫同時播放
     CABasicAnimation 提供了對單一動畫的實現
     CAKeyframeAnimation 關鍵楨動畫,能夠定義行動路線

比較經常使用的是CABasicAnimation、CAKeyframeAnimation和CAAnimationGroup;
   
CABasicAnimation動畫也須要設置變化和變化的時間,經過-setFromValue 和-setToValue 來指定一個開始值和結束值,duration是動畫持續時間。

下面是兩個例子:
  • (void)showPlay{          UIColor *stroke = [UIColor redColor];     CGRect pathFrame = CGRectMake(120, 120, 60, 60);     UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:pathFrame cornerRadius:30];          CAShapeLayer *circleShape = [CAShapeLayer layer];     circleShape.path = path.CGPath;     circleShape.position = CGPointMake(0, 0);     circleShape.fillColor = [UIColor clearColor].CGColor;     circleShape.opacity = 0;     circleShape.strokeColor = stroke.CGColor;     circleShape.lineWidth = 3;          [self.layer addSublayer:circleShape];          CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];     scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];     scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(3, 1, 1)];//x,y,z放大縮小倍數          CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];     alphaAnimation.fromValue = @1;     alphaAnimation.toValue = @0;          CAAnimationGroup *animation = [CAAnimationGroup animation];     animation.animations = @[scaleAnimation, alphaAnimation];     animation.duration = 7.5f;     animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];     animation.repeatCount = 4;     [circleShape addAnimation:animation forKey:nil]; }線程

  • (void)rotateWheel:(UIView*)view {     float totalRotation = 6M_PI;          NSArray keyTimes = @[@0.0, @0.2, @0.8, @1.0]; //0-0.2-0.8-1.0 3段動畫     CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"]; //z軸選擇     animation.duration = 5;     animation.keyTimes = keyTimes;     animation.values = @[@(0totalRotation), @(0.33totalRotation), @(0.67totalRotation), @(1totalRotation)];     animation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],                                   [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear],                                   [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];     [view.layer addAnimation:animation forKey:@"rotateZ"]; }code

###### CADisplayLink
CADisplayLink 其實和CADAnimation同樣 都是QuartzCore.framework裏的類,但這個又是有些特殊的地方,通常都把它於NSTimer放在一塊兒比較,由於這個擁有計時器的功能,精度能達到每秒觸發60次。它和timer同樣是把對象加到runloop中,觸發的時間到了,runloop向對象指定的target發送一次selector消息。 在作一些精細點的動畫,不受其餘動畫或線程干擾,須要指定runloop的模式,就像srollView在滾動時,若是是默認的runloop模式,timer的計時時間會延遲。

以下面一段代碼:爲了實現img1Loading和img2Loading 無縫隙循環移動

#pragma - mark - loadingImageAnimationorm

  • (void)startMoveLoadingImage {     self.moveDisplaylink = [CADisplayLink displayLinkWithTarget:self selector:@selector(bgLoadingImageMove:)];     self.moveDisplaylink.frameInterval = 2;//每秒30次     [self.moveDisplaylink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

}視頻

  • (void)bgLoadingImageMove:(CADisplayLink *)displayLink {     self.linkTimeCount ++;     int perMaxCount = 360; //每一次循環滑動調用的最大次數     [self setLoadingImage:perMaxCount];      }對象

  • (void)setLoadingImage:(int)perMaxCount {     int moveCount = self.linkTimeCount%perMaxCount;//餘數 //    CCLog(@"moveCount %d",moveCount);圖片

    CGRect frame = _img1Loading.frame;     CGFloat imageWidth = frame.size.width - 44; //441     frame.origin.x = -imageWidth/perMaxCount*moveCount;          if (self.img1Loading.frame.origin.x > self.img2Loading.frame.origin.x) {         self.img2Loading.frame = frame;         frame.origin.x += imageWidth;         self.img1Loading.frame = frame;     }     else     {         self.img1Loading.frame = frame;         frame.origin.x += imageWidth;         self.img2Loading.frame = frame;     }          if (moveCount+1 == perMaxCount)     {         self.isNeedChange = YES;     }     if (self.isNeedChange) {         frame.origin.x = imageWidth;         if (self.img1Loading.frame.origin.x > self.img2Loading.frame.origin.x) {             self.img2Loading.frame = frame;         }         else         {             self.img1Loading.frame = frame;         }         self.isNeedChange = false;     }

}

  • (void)stopAnimation {     if (_moveDisplaylink)     {         [self.moveDisplaylink invalidate];         self.moveDisplaylink = nil;         self.linkTimeCount = 0;     } }
相關文章
相關標籤/搜索