iOS實現一個輕微晃動的提示動畫

背景

我們需要用到一個上下輕微晃動的動畫效果,提示有什麼東西,吸引用戶的注意。

方案一

- (UIButton *)moveBtn {
  if (!_moveBtn) {
   _moveBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  _moveBtn.frame = CGRectMake(0,0 ,300,150);
   _moveBtn.enabled = NO;
    [_moveBtn setBackgroundImage:[UIImage imageNamed:@"yangmi"] forState:UIControlStateDisabled];
    [_moveBtn setTitleColor:[UIColor redColor] forState:(UIControlStateNormal)];
    _moveBtn.titleLabel.font = [UIFont systemFontOfSize:10];
    _moveBtn.layer.masksToBounds = YES;
    _moveBtn.layer.cornerRadius = 5.f;
    CGFloat width = [UIScreen mainScreen].bounds.size.width;
    CGFloat height = [UIScreen mainScreen].bounds.size.height;
    _moveBtn.layer.anchorPoint = CGPointMake(0, 1);
    //這句代碼改變了上面原始的frame,這個時候可以設置position
    //也可以設置frame
    //_moveBtn.frame = CGRectMake(width / 2.f - 150,height / 2.f - 75 ,300,150);
    _moveBtn.layer.position = CGPointMake(width / 2.f - 150, height/2.f + 75);
    ///這個點設置很關鍵,可以設置搖動的錨點,同時讓這個按鈕屏幕居中
  }
  return _moveBtn;
}

- (void)shakeAnimationForViewQ:(UIButton *)btn{
    CGFloat secsAngle = M_PI / 30.f;
    [self showAnimationWithTime:secsAngle];
}

- (void)showAnimationWithTime:(CGFloat)angle {
    self.moveBtn.layer.transform = CATransform3DMakeRotation(angle, 0, 0, 1);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        CGFloat secsAngle1;
        if (angle > 0) {
            secsAngle1 = -M_PI / 15.f;
        }else{
            secsAngle1 = M_PI / 15.f;
        }
        [self showAnimationWithTime:secsAngle1];
    });
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.moveBtn];
    [self shakeAnimationForViewQ:self.moveBtn];
}

效果圖

冪冪的性感

第二種方案

起因:上面的方案用transform實現,有點僵硬,動畫看上去不是很好,接下來用CAKeyframeAnimation來實現動畫

- (UIButton *)moveBtn {
  if (!_moveBtn) {
   _moveBtn = [UIButton buttonWithType:UIButtonTypeCustom];
       _moveBtn.frame = CGRectMake(0, 0, 300, 150);
   _moveBtn.enabled = NO;
    [_moveBtn setBackgroundImage:[UIImage imageNamed:@"yangmi"] forState:UIControlStateDisabled];
    [_moveBtn setTitleColor:[UIColor whiteColor] forState:(UIControlStateNormal)];
    _moveBtn.titleLabel.font = [UIFont systemFontOfSize:30];
    [_moveBtn setTitle:@"我就是很美" forState:UIControlStateNormal];
    [_moveBtn setContentHorizontalAlignment:UIControlContentHorizontalAlignmentRight];
    _moveBtn.layer.anchorPoint = CGPointMake(0, 1);
    _moveBtn.layer.masksToBounds = YES;
    _moveBtn.layer.cornerRadius = 5.f;
      CGFloat width = [UIScreen mainScreen].bounds.size.width;
      CGFloat height = [UIScreen mainScreen].bounds.size.height;
     _moveBtn.layer.position = CGPointMake(width / 2.f - 150, height/2.f + 75);
    ///這個點設置很關鍵,可以設置搖動的錨點,這個設置動畫在中間
  }
  return _moveBtn;
}

#pragma mark

- (void)addMoveAnimation:(UIView *)view{
 CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
 animation.delegate = self;
 animation.keyPath = @"transform.rotation";
 animation.values = @[@(radian(0)), @(radian(-20)), @(radian(0)), @(radian(-20)),@(radian(0))];
 animation.duration = 0.7;
 // 動畫的重複執行次數
 animation.repeatCount = 1;
 // 保持動畫執行完畢後的狀態
 animation.removedOnCompletion = NO;
 animation.fillMode = kCAFillModeForwards;
 [view.layer addAnimation:animation forKey:@"shake_animation"];
}

#pragma mark -- 動畫代理
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [self addMoveAnimation:self.moveBtn];
 });
}

#pragma mark - 移除抖動動畫

- (void)removeAnimationShakeWithView:(UIView *)view{
 //結束動畫
 [view.layer removeAnimationForKey:@"shake"];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.moveBtn];
    [self addMoveAnimation:self.moveBtn];
}

效果圖

自信的楊冪

思考題

  • 問:爲什麼在設置爲anchorpoint點之後,需要重新設置frame或者position?
    答: 因爲anchorpoint設置爲(0,1)後,改變了之前默認的(0.5,0.5)
  • 改變anchorPoint後,能算出新的frame嗎
  • 答: 可以,首先得算出最初的poisition,然後再計算
  • 問: 具體步驟
  • 答: 先算position,然後根據anchorpoint畫圖,再做計算,單方面改變anchorPoint一定會改變frame
  • 問:如果父視圖變了,子視圖沒有變,子視圖的frame和bounds會變嗎
  • 答:不變
  • 問: 如果子視圖的anchorPoint也變了呢
  • 答: 子視圖根據父視圖變化後的frame來計算

參考文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章