美文网首页iOS动画动画iOS渲染和动画
iOS仿抖音—加载点赞动画效果

iOS仿抖音—加载点赞动画效果

作者: QuintGao | 来源:发表于2019-06-24 18:17 被阅读0次

    iOS仿抖音短视频

    iOS仿抖音—左右滑动切换效果
    iOS仿抖音—上下滑动播放视频
    iOS仿抖音—评论视图滑动消失
    iOS仿抖音—加载点赞动画效果
    iOS仿抖音—播放视图滑动隐藏

    前言

    前段时间比较忙,最近终于有时间就继续对仿抖音的demo进行更新,本次更新的主要是抖音上的几种动画,下面先来看下效果图:


    抖音

    说明

    经过观察发现抖音主要要以下几种动画效果:
    1、数据加载动画(两个小球来回切换)
    2、视频加载动画(直线向两边扩散)
    3、红心点赞动画(红心由小变大并向四周扩散)
    4、双击点赞动画(多个红心由小变大并逐渐消失)
    于是在经过各种资料查找及自我实践中完成了这四种动画,下面就这几种动画做一下简单说明

    1、数据加载动画

    数据加载

    这个动画大致观察发现是一个红球一个绿球左右来回切换实现的,但仔细观察你会发现,在左右切换的过程中有个黑色小球在不断变大缩小,跟随最上面的球运动。
    因此我们需要添加三个小球,绿球、红球、黑球,默认绿球在左红球在右,黑球在绿球上

        self.containerView = [[UIView alloc] init];
        self.containerView.center = self.center;
        self.containerView.bounds = CGRectMake(0, 0, 2.1f * kBallWidth, 2.0f * kBallWidth);
        [self addSubview:self.containerView];
        
        // 绿球
        self.greenBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kBallWidth, kBallWidth)];
        self.greenBall.center = CGPointMake(kBallWidth * 0.5f, self.containerView.bounds.size.height * 0.5f);
        self.greenBall.layer.cornerRadius = kBallWidth * 0.5f;
        self.greenBall.layer.masksToBounds = YES;
        self.greenBall.backgroundColor = GKColorRGB(35, 246, 235);
        [self.containerView addSubview:self.greenBall];
        
        // 红球
        self.redBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kBallWidth, kBallWidth)];
        self.redBall.center = CGPointMake(self.containerView.bounds.size.width - kBallWidth * 0.5f, self.containerView.bounds.size.height * 0.5f);
        self.redBall.layer.cornerRadius = kBallWidth * 0.5f;
        self.redBall.layer.masksToBounds = YES;
        self.redBall.backgroundColor = GKColorRGB(255, 46, 86);
        [self.containerView addSubview:self.redBall];
        
        // 黑球
        // 第一次动画是正向,绿球在上,红球在下,阴影显示在绿球上
        self.blackBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kBallWidth, kBallWidth)];
        self.blackBall.backgroundColor = GKColorRGB(12, 11, 17);
        self.blackBall.layer.cornerRadius = kBallWidth * 0.5f;
        self.blackBall.layer.masksToBounds = YES;
        [self.greenBall addSubview:self.blackBall];
    

    开始动画,绿球向右放大运动,红球向左缩小运动,绿球到最右边后,红球向右放大运动,绿球向左缩小运动,完成一次循环,黑球是绿球和红球的重合部分,主要代码如下:

    - (void)updateBallAnimations {
        if (self.moveDirection == GKBallMoveDirectionPositive) { // 正向
            CGPoint center = self.greenBall.center;
            center.x += kBallSpeed;
            self.greenBall.center = center;
            
            center = self.redBall.center;
            center.x -= kBallSpeed;
            self.redBall.center = center;
            
            // 缩放动画,绿球放大,红球缩小
            self.greenBall.transform = [self ballLargerTransformOfCenterX:center.x];
            self.redBall.transform   = [self ballSmallerTransformOfCenterX:center.x];
            
            // 更新黑球位置
            CGRect blackBallFrame = [self.redBall convertRect:self.redBall.bounds toCoordinateSpace:self.greenBall];
            self.blackBall.frame = blackBallFrame;
            self.blackBall.layer.cornerRadius = self.blackBall.bounds.size.width * 0.5f;
            
            // 更新方向 改变三个球的相对位置
            if (CGRectGetMaxX(self.greenBall.frame) >= self.containerView.bounds.size.width || CGRectGetMinX(self.redBall.frame) <= 0) {
                // 切换为反向
                self.moveDirection = GKBallMoveDirectionNegative;
                
                // 反向运动时,红球在上,绿球在下
                [self.containerView bringSubviewToFront:self.redBall];
                
                // 黑球放在红球上面
                [self.redBall addSubview:self.blackBall];
                
                // 重置动画
                [self resetAnimation];
            }
        }else if (self.moveDirection == GKBallMoveDirectionNegative) { // 反向
            // 更新绿球位置
            CGPoint center = self.greenBall.center;
            center.x -= kBallSpeed;
            self.greenBall.center = center;
            
            // 更新红球位置
            center = self.redBall.center;
            center.x += kBallSpeed;
            self.redBall.center = center;
            
            // 缩放动画 红球放大 绿球缩小
            self.redBall.transform = [self ballLargerTransformOfCenterX:center.x];
            self.greenBall.transform = [self ballSmallerTransformOfCenterX:center.x];
            
            // 更新黑球位置
            CGRect blackBallFrame = [self.greenBall convertRect:self.greenBall.bounds toCoordinateSpace:self.redBall];
            self.blackBall.frame = blackBallFrame;
            self.blackBall.layer.cornerRadius = self.blackBall.bounds.size.width * 0.5f;
            
            // 更新方向 改变三个球的相对位置
            if (CGRectGetMinX(self.greenBall.frame) <= 0 || CGRectGetMaxX(self.redBall.frame) >= self.containerView.bounds.size.width) {
                // 切换为正向
                self.moveDirection = GKBallMoveDirectionPositive;
                // 正向运动 绿球在上 红球在下
                [self.containerView bringSubviewToFront:self.greenBall];
                // 黑球放在绿球上面
                [self.greenBall addSubview:self.blackBall];
                // 重置动画
                [self resetAnimation];
            }
        }
    }
    

    具体代码可在demo中的GKBallLoadingView中查看。

    2、视频加载动画

    视频加载

    这个动画比较简单,首先以x轴为中心进行缩放动画,然后再修改的透明度即可,主要代码如下:

        // 创建动画组
        CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
        animationGroup.duration = GKLineLoadingDuration;
        animationGroup.beginTime = CACurrentMediaTime();
        animationGroup.repeatCount = MAXFLOAT;
        animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        
        // x轴缩放动画(transform.scale是以view的中心点为中心开始缩放的)
        CABasicAnimation *scaleAnimation = [CABasicAnimation animation];
        scaleAnimation.keyPath = @"transform.scale.x";
        scaleAnimation.fromValue = @(1.0f);
        scaleAnimation.toValue = @(1.0f * self.superview.frame.size.width);
        
        // 透明度渐变动画
        CABasicAnimation *alphaAnimation = [CABasicAnimation animation];
        alphaAnimation.keyPath = @"opacity";
        alphaAnimation.fromValue = @(1.0f);
        alphaAnimation.toValue = @(0.5f);
        
        animationGroup.animations = @[scaleAnimation, alphaAnimation];
        // 添加动画
        [self.layer addAnimation:animationGroup forKey:nil];
    

    具体代码可在demo中的GKLineLoadingView中查看。

    3、红心点赞动画

    红心点赞

    这个动画的主要是通过CAShapeLayer和贝赛尔曲线绘制三角形,循环创建6次在6个方向绘制三角形,并加入动画,然后进行红心的缩放动画,主要代码如下:

        if (isLike) {
            CGFloat length      = 30;
            CGFloat duration    = 0.5f;
            for (NSInteger i = 0; i < 6; i++) {
                CAShapeLayer *layer = [CAShapeLayer layer];
                layer.position = self.likeBeforeImgView.center;
                layer.fillColor = GKColorRGB(232, 50, 85).CGColor;
    
                UIBezierPath *startPath = [UIBezierPath bezierPath];
                [startPath moveToPoint:CGPointMake(-2, -length)];
                [startPath addLineToPoint:CGPointMake(2, -length)];
                [startPath addLineToPoint:CGPointMake(0, 0)];
                layer.path = startPath.CGPath;
    
                layer.transform = CATransform3DMakeRotation(M_PI / 3.0f * i, 0, 0, 1.0);
                [self.layer addSublayer:layer];
    
                CAAnimationGroup *group = [CAAnimationGroup animation];
                group.removedOnCompletion = NO;
                group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
                group.fillMode = kCAFillModeForwards;
                group.duration = duration;
    
                CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
                scaleAnim.fromValue = @(0.0f);
                scaleAnim.toValue = @(1.0f);
                scaleAnim.duration = duration * 0.2f;
    
                UIBezierPath *endPath = [UIBezierPath bezierPath];
                [endPath moveToPoint:CGPointMake(-2, -length)];
                [endPath addLineToPoint:CGPointMake(2, -length)];
                [endPath addLineToPoint:CGPointMake(0, -length)];
    
                CABasicAnimation *pathAnim = [CABasicAnimation animationWithKeyPath:@"path"];
                pathAnim.fromValue = (__bridge id)layer.path;
                pathAnim.toValue = (__bridge id)endPath.CGPath;
                pathAnim.beginTime = duration * 0.2f;
                pathAnim.duration = duration * 0.8f;
    
                [group setAnimations:@[scaleAnim, pathAnim]];
                [layer addAnimation:group forKey:nil];
            }
            self.likeAfterImgView.hidden = NO;
            self.likeAfterImgView.alpha = 0.0f;
            
            self.likeAfterImgView.transform = CGAffineTransformMakeScale(0.1f, 0.1f);
            
            [UIView animateWithDuration:0.15 animations:^{
                self.likeAfterImgView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
                self.likeAfterImgView.alpha = 1.0f;
                self.likeBeforeImgView.alpha = 0.0f;
            } completion:^(BOOL finished) {
                self.likeAfterImgView.transform = CGAffineTransformIdentity;
                self.likeBeforeImgView.alpha = 1.0f;
            }];
        }else {
            self.likeAfterImgView.alpha = 1.0f;
            self.likeAfterImgView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
            [UIView animateWithDuration:0.15 animations:^{
                self.likeAfterImgView.transform = CGAffineTransformMakeScale(0.3f, 0.3f);
            } completion:^(BOOL finished) {
                self.likeAfterImgView.transform = CGAffineTransformIdentity;
                self.likeAfterImgView.hidden = YES;
            }];
        }
    

    具体代码可在demo中的GKLikeView中查看

    4、双击点赞动画

    双击点赞

    这个动画主要是通过在- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法中根据触摸的位置不停创建红心,并放大、透明,然后销毁,主要代码如下:

    - (void)createAnimationWithTouch:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        UITouch *touch = [touches anyObject];
        if (touch.tapCount <= 1.0f) return;
        
        CGPoint point = [touch locationInView:touch.view];
        UIImage *image = [UIImage imageNamed:@"likeHeart"];
        UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, ADAPTATIONRATIO * 160.0f, ADAPTATIONRATIO * 160.0f)];
        imgView.image = image;
        imgView.contentMode = UIViewContentModeScaleAspectFill;
        imgView.center = point;
        
        // 随机左右显示
        int leftOrRight = arc4random() % 2;
        leftOrRight = leftOrRight ? leftOrRight : -1;
        imgView.transform = CGAffineTransformRotate(imgView.transform, M_PI / 9.0f * leftOrRight);
        [touch.view addSubview:imgView];
        
        // 出现的时候回弹一下
        __block UIImageView *blockImgV = imgView;
        __block UIImage *blockImage = image;
        
        [UIView animateWithDuration:0.1 animations:^{
            blockImgV.transform = CGAffineTransformScale(blockImgV.transform, 1.2f, 1.2f);
        } completion:^(BOOL finished) {
            blockImgV.transform = CGAffineTransformScale(blockImgV.transform, 0.8f, 0.8f);
            
            // 向上飘,放大,透明
            [self performSelector:@selector(animationToTop:) withObject:@[blockImgV, blockImage] afterDelay:0.3f];
        }];
    }
    

    具体代码可在demo中的GKDoubleLikeView中查看。

    最后

    上面提到的所有动画都可以在github上的demoGKDYVideo中查看,如果觉得不错,还请来个star!

    赞赏

    您的赞赏是对我最大的支持

    微信赞赏 支付宝赞赏

    参考

    抖音点赞动画实现—iOS
    iOS开发_仿抖音点赞动画功能的实现

    相关文章

      网友评论

        本文标题:iOS仿抖音—加载点赞动画效果

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