美文网首页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