美文网首页
[1]会员升级动画(无限旋转+缩放)

[1]会员升级动画(无限旋转+缩放)

作者: 默然走一生 | 来源:发表于2019-04-22 17:49 被阅读0次

会员升级的动画根据设计提供的UI,为了减小图片的大小,让设计把动画分为了两部分,第一部分为连续的47张图片利用UIImage的animationImages进行播放,第二部分的无限旋转和缩放则用CABasicAnimation实现。

播放png动画,首先要获取图片,说到图片获取的方法,就得看API文档。

UIImage生成实例的方法有:

  • 1)imageNamed

      从指定文件返回对象。
      这个方法有个比较特殊的地方:该方法首先从系统缓存中寻找该图片,如果有,则从缓存中获取;如果没有,则获取图片,再把图片加入缓存;
    
  • 2)imageWithContentFile

      从指定文件路径中加载对象并返回。但是该方法不会缓存对象。
    
  • 3)imageWithData

      根据NSData返回对象实例
    

我们不需要缓存图片对象,如果缓存了,内存会暴增。所以我们选择imageWithContentFile这个方法来加载图片

- (void)levelupAnimationWith:(NSString *)level
{
        level = [level lowercaseString];//改成小写
        NSMutableArray * imageArray = [NSMutableArray array];
        for (NSInteger i = 0; i <= levelupImageCount; i++) {
            NSString * imagePath =  [self getBundleImagePathWith:level num:i];
            UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
            [imageArray addObject:image];
        }
        //最后一张图片
        self.lastImagePath = [self getBundleImagePathWith:level num:levelupImageCount];
        //图片播放一次所需时长
        _levelupImageView.animationDuration = animiationTime;
        //图片播放次数,1
        _levelupImageView.animationRepeatCount = 1;
        //设置动画图片数组
        _levelupImageView.animationImages = imageArray;
        [_levelupImageView startAnimating];
        [self performSelector:@selector(endAinimation) withObject:nil afterDelay:animiationTime];
        //添加到window上
        if(self.superview == nil){
            self.alpha = 0.;
            [[LJBHSLevelupView mainWindow] addSubview:self];
            [UIView animateWithDuration:0.25 animations:^{
                self.alpha = 1.;
            } completion:^(BOOL finished) {
            }];
        }
}
//拼接Bundle path
- (NSString *) getBundleImagePathWith:(NSString *)level num:(NSInteger)num
{
    NSString *levelBundle = [[NSBundle mainBundle] pathForResource:@"levelup" ofType:@"bundle"];
    NSString * levelupPrefix = [NSString stringWithFormat:@"levelup_%@",level];
    NSString * imageName = [NSString stringWithFormat:@"%@_%02ld@2x",levelupPrefix,(long)num];
    NSString * imagePath =  [[NSBundle bundleWithPath:levelBundle] pathForResource:imageName ofType:@"png" inDirectory:levelupPrefix];
    return imagePath;
}

- (void)endAinimation
{
    [_levelupImageView stopAnimating];
    _levelupImageView.animationImages = nil;
    [_levelupImageView setImage:[UIImage imageWithContentsOfFile:self.lastImagePath]];
    _cancelBtn.hidden = NO;
    _rotateImageView.hidden = NO;
    _shareBtn.hidden = NO;
    
    [self addRotationAnimation];
    [self addZoomAnimation];
}

/*************旋转动画*************/
-(void)addRotationAnimation
{
    CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.toValue = [NSNumber numberWithFloat:M_PI*2.0];
    rotationAnimation.duration = 6.0f;//动画时间
    rotationAnimation.repeatCount = HUGE_VALF;//设置重复次数,HUGE_VALF可看做无穷大,起到循环动画的效果
    [_rotateImageView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}
/*************缩放动画*************/
-(void)addZoomAnimation
{
    CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.scale"];
    animation.fromValue=[NSNumber numberWithFloat:1.1];
    animation.toValue=[NSNumber numberWithFloat:0.6];
    animation.duration=1.0f;//动画时间
    animation.autoreverses=YES;//设置这个属性表示完成动画后会回到执行动画之前的状态
    animation.repeatCount=HUGE_VALF;//设置重复次数,HUGE_VALF可看做无穷大,起到循环动画的效果
    [_rotateImageView.layer addAnimation:animation forKey:@"zoomAnimation"];
}

CABasicAnimation的动画属性和说明

  • @property(nullable, strong) id fromValue; //改变属性的起始值

  • @property(nullable, strong) id toValue;//改变属性的结束值

  • @property(nullable, strong) id byValue; //改变属性相同起始值的改变量

  • @property float repeatCount;//重复的次数。不停重复设置为 HUGE_VALF

  • @property CFTimeInterval repeatDuration;//设置动画的时间。在该时间内动画一直执行,不计次数。

  • @property CFTimeInterval beginTime;//指定动画开始的时间。从开始延迟几秒的话,设置为【CACurrentMediaTime() + 秒数】 的方式

  • @property(nullable, copy) NSArray<CAMediaTimingFunction *> *timingFunctions;//设置动画的速度变化

  • @property BOOL autoreverses;//动画结束时是否执行逆动画

防止动画结束后回到初始状态

只需设置removedOnCompletion、fillMode两个属性就可以了。

animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;

为什么动画结束后返回原状态?

首先我们需要搞明白一点的是,layer动画运行的过程是怎样的?其实在我们给一个视图添加layer动画时,真正移动并不是我们的视图本身,而是 presentation layer 的一个缓存。动画开始时 presentation layer开始移动,原始layer隐藏,动画结束时,presentation layer从屏幕上移除,原始layer显示。这就解释了为什么我们的视图在动画结束后又回到了原来的状态,因为它根本就没动过。
这个同样也可以解释为什么在动画移动过程中,我们为何不能对其进行任何操作。
所以在我们完成layer动画之后,最好将我们的layer属性设置为我们最终状态的属性,然后将presentation layer 移除掉。

相关文章

网友评论

      本文标题:[1]会员升级动画(无限旋转+缩放)

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