#import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self test]; [self test2]; [self test3]; [self test4]; [self test5]; [self test7]; } //- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ // // //} #pragma mark - 小方塊 - (void)test{ CALayer *layer = [[CALayer alloc] init]; layer.bounds = CGRectMake(0, 0, 100, 100); layer.backgroundColor = [UIColor orangeColor].CGColor; layer.delegate = self; [self.view.layer addSublayer:layer]; layer.anchorPoint = CGPointMake(0.5, 0.5); layer.position = CGPointMake(100, 100); CABasicAnimation *ani = [[CABasicAnimation alloc] init]; ani.keyPath = @"transform.scale"; ani.fromValue = [NSNumber numberWithFloat:0.5]; ani.toValue = [NSNumber numberWithFloat:1.8]; ani.repeatCount = MAXFLOAT; ani.duration = 1.0f; // 當動畫執行到toValue指定的狀態時是從toValue的狀態逆回去,仍是直接跳到fromValue的狀態再執行一遍 ani.autoreverses = YES; ani.fillMode = kCAFillModeForwards; ani.removedOnCompletion = NO; [layer addAnimation:ani forKey:nil]; } - (void)animationDidStart:(CAAnimation *)anim{ NSLog(@"動畫開始"); } - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{ NSLog(@"動畫結束"); } - (void)test2{ CALayer *layer = [[CALayer alloc] init]; layer.bounds = CGRectMake(0, 0, 50, 50); layer.backgroundColor = [UIColor redColor].CGColor; layer.anchorPoint = CGPointMake(0, 0); layer.position = CGPointMake(0, 200); [self.view.layer addSublayer:layer]; CABasicAnimation *ani = [[CABasicAnimation alloc] init]; ani.keyPath = @"transform.translation.x"; ani.fromValue = [NSNumber numberWithFloat:60]; ani.toValue = [NSNumber numberWithFloat:300]; ani.autoreverses = YES; ani.fillMode = kCAFillModeForwards; ani.removedOnCompletion = NO; ani.duration = 1; ani.repeatCount = MAXFLOAT; [layer addAnimation:ani forKey:nil]; } - (void)test3{ CALayer *layer = [[CALayer alloc] init]; layer.bounds = CGRectMake(0, 0, 50, 50); layer.backgroundColor = [UIColor blueColor].CGColor; layer.anchorPoint = CGPointMake(0.5, 0); layer.position = CGPointMake(100, 0); [self.view.layer addSublayer:layer]; CABasicAnimation *ani = [[CABasicAnimation alloc] init]; ani.keyPath = @"transform.translation.y"; ani.fromValue = [NSNumber numberWithFloat:0]; ani.toValue = [NSNumber numberWithFloat:self.view.frame.size.height - 50]; ani.fillMode = kCAFillModeBoth; ani.removedOnCompletion = NO; ani.autoreverses = YES; ani.duration = 2; ani.repeatCount = MAXFLOAT; CABasicAnimation *ani2 = [[CABasicAnimation alloc] init]; ani2.keyPath = @"transform.scale"; ani2.fromValue = [NSNumber numberWithFloat:1]; ani2.toValue = [NSNumber numberWithFloat:2.8]; ani2.fillMode = kCAFillModeBoth; ani2.removedOnCompletion = NO; ani2.autoreverses = YES; ani2.duration = 1; ani2.repeatCount = MAXFLOAT; CABasicAnimation *ani3 = [[CABasicAnimation alloc] init]; ani3.keyPath = @"transform.rotation.y"; ani3.fromValue = [NSNumber numberWithFloat:1]; ani3.toValue = [NSNumber numberWithFloat:M_PI_2*2]; ani3.fillMode = kCAFillModeBoth; ani3.removedOnCompletion = NO; ani3.autoreverses = YES; ani3.duration = 0.5; ani3.repeatCount = MAXFLOAT; CAAnimationGroup *group = [[CAAnimationGroup alloc] init]; group.duration = 2; group.animations = @[ani,ani2,ani3]; group.repeatCount = MAXFLOAT; group.autoreverses = YES; [layer addAnimation:group forKey:nil]; } - (void)test5{ CALayer *layer = [[CALayer alloc] init]; layer.bounds = CGRectMake(0, 0, 50, 50); layer.backgroundColor = [UIColor greenColor].CGColor; layer.anchorPoint = CGPointMake(0.5, 0); layer.position = CGPointMake(100, 0); [self.view.layer addSublayer:layer]; CAKeyframeAnimation *ani = [[CAKeyframeAnimation alloc] init]; ani.keyPath = @"position"; CGPoint p1 = CGPointMake(80, 80); CGPoint p2 = CGPointMake(250, 80); CGPoint p3 = CGPointMake(250, 250); CGPoint p4 = CGPointMake(80, 250); CGPoint p5 = CGPointMake(80, 80); // ani.values = @[[NSValue valueWithCGPoint:p1], // [NSValue valueWithCGPoint:p2], // [NSValue valueWithCGPoint:p3], // [NSValue valueWithCGPoint:p4], // [NSValue valueWithCGPoint:p5]]; // ani.keyTimes = @[@0.25,@0.25,@0.25,@0.25]; CGMutablePathRef path = CGPathCreateMutable(); // CGPathAddRect(path, NULL, CGRectMake(0, 0, 200, 200)); // CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 0, 200, 200)); CGPathAddArc(path, NULL, 200, 200, 100, 0, 2*M_PI, YES); // CGPathMoveToPoint(path, NULL, 0, 0); // CGPathAddLineToPoint(path, NULL, 300, 300); ani.path = path; ani.duration = 2; ani.repeatCount = MAXFLOAT; ani.removedOnCompletion = NO; ani.fillMode = kCAFillModeForwards; // ani.autoreverses = YES; [layer addAnimation:ani forKey:nil]; } - (void)test4{ CALayer *layer = [[CALayer alloc] init]; layer.bounds = CGRectMake(0, 0, 50, 50); layer.backgroundColor = [UIColor grayColor].CGColor; layer.anchorPoint = CGPointMake(0.5, 0); layer.position = CGPointMake(100, 0); [self.view.layer addSublayer:layer]; CASpringAnimation *ani = [[CASpringAnimation alloc] init]; ani.keyPath = @"position"; ani.fromValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)]; ani.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 400)]; //這個屬性設置彈簧重物的質量 會影響慣性 必須大於0 默認爲1 ani.mass = 1; //設置彈簧的剛度係數,必須大於0 默認爲100 這個越大 則回彈越快 ani.stiffness = 50; //阻尼係數 默認爲10 必須大於0 這個值越大 回彈的幅度越小 ani.damping = 2.5; //初始速度 ani.initialVelocity = 0; NSLog(@"ani.settlingDuration %lf",ani.settlingDuration); ani.duration = ani.settlingDuration; ani.repeatCount = MAXFLOAT; ani.removedOnCompletion = NO; ani.fillMode = kCAFillModeForwards; // ani.autoreverses = YES; [layer addAnimation:ani forKey:nil]; } - (void)test7{ // CALayer *layer = [[CALayer alloc] init]; // layer.bounds = CGRectMake(0, 0, 50, 50); // layer.backgroundColor = [UIColor grayColor].CGColor; // layer.anchorPoint = CGPointMake(0.5, 0.5); // layer.position = CGPointMake(self.view.frame.size.width - 80, 40); // // [self.view.layer addSublayer:layer]; UIImageView *imgView = [[UIImageView alloc] init]; imgView.frame = CGRectMake(self.view.frame.size.width - 120, 40, 100, 100); imgView.image = [UIImage imageNamed:@"通風"]; [self.view addSubview:imgView]; CALayer *layer = imgView.layer; layer.anchorPoint = CGPointMake(0.5, 0.5); CABasicAnimation *ani = [[CABasicAnimation alloc] init]; ani.keyPath = @"transform.rotation.z"; ani.fromValue = @0; ani.toValue = [NSNumber numberWithFloat:2*M_PI]; ani.removedOnCompletion = NO; ani.fillMode = kCAFillModeForwards; ani.repeatCount = MAXFLOAT; ani.duration = 3; [layer addAnimation:ani forKey:nil]; } @end
keyPath: 決定基礎動畫的類型,該值不能隨便取,一旦取錯就達不到想要的效果。要改變位置就取position,要改變透明度就取opacity,要等比例縮放就取transform.scale...更多key請看下面的表1,要儘可能能記住這些內容動畫
fromValue: 動畫的起始狀態值,雖然iOS文檔給出的類型是id,不過這裏應該傳NSValue對象,好比NSNumber(NSNubmer繼承自NSValue)。其具體含義spa
autoreverse: 當動畫執行到toValue指定的狀態時是從toValue的狀態逆回去,仍是直接跳到fromValue的狀態再執行一遍code
fileMode: fillMode的做用就是決定當前對象過了非active時間段的行爲. 非active時間段是指動畫開始以前以及動畫結束以後。若是是一個動畫CAAnimation,則須要將其removedOnCompletion設置爲NO,要否則fillMode不起做用. 下面來說各個fillMode的意義:orm
kCAFillModeRemoved 這個是默認值,也就是說當動畫開始前和動畫結束後,動畫對layer都沒有影響,動畫結束後,layer會恢復到以前的狀態對象
kCAFillModeForwards 當動畫結束後,layer會一直保持着動畫最後的狀態blog
kCAFillModeBackwards 這個和kCAFillModeForwards是相對的,就是在動畫開始前,你只要將動畫加入了一個layer,layer便當即進入動畫的初始狀態。由於有可能出現fromValue不是目前layer的初始狀態的狀況,若是fromValue就是layer當前的狀態,則這個參數就沒太大意義。繼承
kCAFillModeBoth 理解了上面兩個,這個就很好理解了,這個其實就是上面兩個的合成.動畫加入後開始以前,layer便處於動畫初始狀態,動畫結束後layer保持動畫最後的狀態.ip