iOS仿抖音—加載點贊動畫效果

iOS仿抖音短視頻

iOS仿抖音—左右滑動切換效果
iOS仿抖音—上下滑動播放視頻
iOS仿抖音—評論視圖滑動消失
iOS仿抖音—加載點贊動畫效果
iOS仿抖音—播放視圖滑動隱藏

前言

前段時間比較忙,最近終于有時間就繼續(xù)對仿抖音的demo進行更新,本次更新的主要是抖音上的幾種動畫,下面先來看下效果圖:


抖音

說明

經(jīng)過觀察發(fā)現(xiàn)抖音主要要以下幾種動畫效果:
1、數(shù)據(jù)加載動畫(兩個小球來回切換)
2、視頻加載動畫(直線向兩邊擴散)
3、紅心點贊動畫(紅心由小變大并向四周擴散)
4、雙擊點贊動畫(多個紅心由小變大并逐漸消失)
于是在經(jīng)過各種資料查找及自我實踐中完成了這四種動畫,下面就這幾種動畫做一下簡單說明

1、數(shù)據(jù)加載動畫

數(shù)據(jù)加載

這個動畫大致觀察發(fā)現(xiàn)是一個紅球一個綠球左右來回切換實現(xiàn)的,但仔細觀察你會發(fā)現(xiàn),在左右切換的過程中有個黑色小球在不斷變大縮小,跟隨最上面的球運動。
因此我們需要添加三個小球,綠球、紅球、黑球,默認綠球在左紅球在右,黑球在綠球上

    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];

開始動畫,綠球向右放大運動,紅球向左縮小運動,綠球到最右邊后,紅球向右放大運動,綠球向左縮小運動,完成一次循環(huán),黑球是綠球和紅球的重合部分,主要代碼如下:

- (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軸為中心進行縮放動畫,然后再修改的透明度即可,主要代碼如下:

    // 創(chuàng)建動畫組
    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和貝賽爾曲線繪制三角形,循環(huán)創(chuàng)建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方法中根據(jù)觸摸的位置不停創(chuàng)建紅心,并放大、透明,然后銷毀,主要代碼如下:

- (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];
    
    // 出現(xiàn)的時候回彈一下
    __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!

贊賞

您的贊賞是對我最大的支持

微信贊賞
支付寶贊賞

參考

抖音點贊動畫實現(xiàn)—iOS
iOS開發(fā)_仿抖音點贊動畫功能的實現(xiàn)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 前言 今天給大家分享一下抖音的點贊動畫的實現(xiàn), 廢話不多說上圖 本篇文章主要包含技術點: CAShapeLayer...
    iOS猿_員閱讀 13,981評論 7 50
  • text-align: center的作用是什么,作用在什么元素上?能讓什么元素水平居中text-align屬性通...
    YangJeremy閱讀 650評論 0 50
  • 寫作第二天 起床:6點鐘起床 天氣:晴 心情:興奮 任務清單 周目標·完成進度 學習·信息·閱讀 健康·飲食·鍛煉...
    愛生活_3b83閱讀 227評論 0 0

友情鏈接更多精彩內容