JumpStar

作者: JoyceZhao | 来源:发表于2016-07-29 09:29 被阅读58次
    • 涉及到的技术点

      • CoreAnimation的基本单位
      • 图片弹跳
      • 翻转动画
      • 我们看到的现象是:如果以一个初速度往上抛一个物体,你的感觉是物体上抛过程花费的时间短,下落花费的时间长。所以我们在做动画中需要做这些违背物理规律的事情:即把下落的时间设置得比上弹的长。
    • JumpStar动画实现的思路

      • 动画分为两个阶段:一个弹上去的阶段,一个落下来的阶段。弹上去的过程让视图绕 y 轴旋转 90 °,此时第一阶段的动画结束。在代理方法 animationDidStop 中开始第二个动画 —— 下落。在这个阶段一开始立刻替换图片, 随后在落下的同时让视图继续旋转 90°。我们要在下落动画结束之后 removeAllAnimations。
    • JumpStar动画的具体实现步骤

      • 界面布局如图所示


        界面布局图5.png
      • ZQJumpStarView的具体代码如下

      //  ZQJumpStarView.h
      
      #import <UIKit/UIKit.h>
      
      typedef enum : NSUInteger {
          NONMark,
          Mark,
      }STATE;
      
      @interface ZQJumpStarView : UIView
      
      /** 图片的状态 */
      @property(nonatomic, assign, setter=setState:)STATE state;
      
      /** 被标记的图片 */
      @property(nonatomic,strong)UIImage *markedImage;
      
      /** 未被标记的图片 */
      @property(nonatomic, strong)UIImage *non_markedImage;
      
      /** 动画 */
      -(void)animation;
      
      @end
      
      //  ZQJumpStarView.m
      
      #import "ZQJumpStarView.h"
      
      /** 上升时间的宏 */
      #define jumpDuration 0.125
      /** 下降时间的宏 */
      #define downDuration 0.215
      
      @interface ZQJumpStarView()
      
      /** 图片View */
      @property(nonatomic, strong)UIImageView *starView;
      
      /** 阴影View */
      @property(nonatomic, strong)UIImageView *shadowView;
      
      @end
      
      @implementation ZQJumpStarView {
      
          /** 动画执行 */
          BOOL animating;
      }
      
      -(instancetype)init {
      
          self = [super init];
          if (self) {
      
          }
          return self;
      }
      
      /** 布局子视图 */
      -(void)layoutSubviews {
      
          [super layoutSubviews];
      
          self.backgroundColor = [UIColor clearColor];
      
          if (self.starView == nil) {
              self.starView = [[UIImageView alloc] initWithFrame:CGRectMake(self.bounds.size.width / 2 - (self.bounds.size.width - 6) / 2, 0, self.bounds.size.width - 6, self.bounds.size.height - 6)];
      
              self.starView.contentMode = UIViewContentModeScaleToFill;
              [self addSubview:self.starView];
          }
          if (self.shadowView == nil) {
              self.shadowView = [[UIImageView alloc] initWithFrame:CGRectMake(self.bounds.size.width / 2 - 10 / 2, self.bounds.size.height - 3, 10, 3)];
      
              self.shadowView.alpha = 0.4;
              self.shadowView.image = [UIImage imageNamed:@"shadow_new"];
              [self addSubview:self.shadowView];
          }
      }
      
      /** 图片状态的set方法 */
      -(void)setState:(STATE)state {
      
          _state = state;
          self.starView.image = _state == Mark ? _markedImage : _non_markedImage;
      }
      
      /** 动画 */
      -(void)animation {
      
          if (animating == YES) {
              return;
          }
      
          animating = YES;
      
          CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
          transformAnimation.fromValue = @(0);
          transformAnimation.toValue = @(M_PI_2);
          transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
      
          CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position.y"];
          positionAnimation.fromValue = @(self.starView.center.y);
          positionAnimation.toValue = @(self.starView.center.y
          - 14);
          positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
      
          CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
          animationGroup.duration = jumpDuration;
          animationGroup.fillMode = kCAFillModeForwards;
          animationGroup.removedOnCompletion = NO;
          animationGroup.delegate = self;
          animationGroup.animations = @[transformAnimation, positionAnimation];
      
          [self.starView.layer addAnimation:animationGroup forKey:@"jumpUp"];
      }
      
      /** 上升动画开始 */
      -(void)animationDidStart:(CAAnimation *)anim {
      
          if ([anim isEqual:[self.starView.layer animationForKey:@"jumpUp"]]) {
              [UIView animateWithDuration:jumpDuration delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{
                  _shadowView.alpha = 0.2;
                  _shadowView.bounds = CGRectMake(0, 0, _shadowView.bounds.size.width * 1.6, _shadowView.bounds.size.height);
              } completion:NULL];
          } else if ([anim isEqual:[self.starView.layer animationForKey:@"jumpDown"]]) {
      
              [UIView animateWithDuration:jumpDuration delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{
                  _shadowView.alpha = 0.4;
                  _shadowView.bounds = CGRectMake(0, 0, _shadowView.bounds.size.width / 1.6, _shadowView.bounds.size.height);
              } completion:NULL];
          }
      }
      
      /** 下降动画开始 */
      -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
      
          if ([anim isEqual:[self.starView.layer animationForKey:@"jumpUp"]]) {
              self.state = self.state == Mark ? NONMark : Mark;
              NSLog(@"state:%ld", _state);
      
              CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
              transformAnimation.fromValue = @(M_PI_2);
              transformAnimation.toValue = @(M_PI);
              transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
      
              CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position.y"];
              positionAnimation.fromValue = @(self.starView.center.y - 14);
              positionAnimation.toValue = @(self.starView.center.y);
              positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
      
              CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
              animationGroup.duration = downDuration;
              animationGroup.fillMode = kCAFillModeForwards;
              animationGroup.removedOnCompletion = NO;
              animationGroup.delegate = self;
              animationGroup.animations = @[transformAnimation, positionAnimation];
      
              [self.starView.layer addAnimation:animationGroup forKey:@"jumpDown"];
          } else if ([anim isEqual:[self.starView.layer animationForKey:@"jumpDown"]]) {
      
              [self.starView.layer removeAllAnimations];
              animating = NO;
          }
      }
      
      @end
      
      • ViewController的具体代码如下
      //  ViewController.m
      
      #import "ViewController.h"
      #import "ZQJumpStarView.h"
      
      @interface ViewController ()
      
      /** 动画View */
      @property (weak, nonatomic) IBOutlet ZQJumpStarView *jumpStarView;
      
      @end
      
      @implementation ViewController
      
      -(void)viewDidLoad {
          [super viewDidLoad];
      
          [_jumpStarView layoutIfNeeded];
          _jumpStarView.markedImage = [UIImage imageNamed:@"icon_star_incell"];
          _jumpStarView.non_markedImage = [UIImage imageNamed:@"blue_dot"];
          _jumpStarView.state = NONMark;
      }
      
      -(IBAction)tapped:(id)sender {
      
          [_jumpStarView animation];
      }
      @end
      
    • 运行结果如图所示

      运行结果图5.gif

    相关文章

      网友评论

        本文标题:JumpStar

        本文链接:https://www.haomeiwen.com/subject/slczjttx.html