iOS仿抖音—加載點(diǎn)贊動(dòng)畫(huà)效果

iOS仿抖音短視頻

iOS仿抖音—左右滑動(dòng)切換效果
iOS仿抖音—上下滑動(dòng)播放視頻
iOS仿抖音—評(píng)論視圖滑動(dòng)消失
iOS仿抖音—加載點(diǎn)贊動(dòng)畫(huà)效果
iOS仿抖音—播放視圖滑動(dòng)隱藏

前言

前段時(shí)間比較忙淹冰,最近終于有時(shí)間就繼續(xù)對(duì)仿抖音的demo進(jìn)行更新埃元,本次更新的主要是抖音上的幾種動(dòng)畫(huà)侯养,下面先來(lái)看下效果圖:


抖音

說(shuō)明

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

1爬骤、數(shù)據(jù)加載動(dòng)畫(huà)

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

這個(gè)動(dòng)畫(huà)大致觀(guān)察發(fā)現(xiàn)是一個(gè)紅球一個(gè)綠球左右來(lái)回切換實(shí)現(xiàn)的充石,但仔細(xì)觀(guān)察你會(huì)發(fā)現(xiàn),在左右切換的過(guò)程中有個(gè)黑色小球在不斷變大縮小霞玄,跟隨最上面的球運(yùn)動(dòng)骤铃。
因此我們需要添加三個(gè)小球拉岁,綠球、紅球惰爬、黑球喊暖,默認(rè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];
    
    // 黑球
    // 第一次動(dòng)畫(huà)是正向撕瞧,綠球在上陵叽,紅球在下,陰影顯示在綠球上
    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];

開(kāi)始動(dòng)畫(huà)丛版,綠球向右放大運(yùn)動(dòng)巩掺,紅球向左縮小運(yùn)動(dòng),綠球到最右邊后页畦,紅球向右放大運(yùn)動(dòng)胖替,綠球向左縮小運(yùn)動(dòng),完成一次循環(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;
        
        // 縮放動(dòng)畫(huà),綠球放大州胳,紅球縮小
        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;
        
        // 更新方向 改變?nèi)齻€(gè)球的相對(duì)位置
        if (CGRectGetMaxX(self.greenBall.frame) >= self.containerView.bounds.size.width || CGRectGetMinX(self.redBall.frame) <= 0) {
            // 切換為反向
            self.moveDirection = GKBallMoveDirectionNegative;
            
            // 反向運(yùn)動(dòng)時(shí)记焊,紅球在上,綠球在下
            [self.containerView bringSubviewToFront:self.redBall];
            
            // 黑球放在紅球上面
            [self.redBall addSubview:self.blackBall];
            
            // 重置動(dòng)畫(huà)
            [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;
        
        // 縮放動(dòng)畫(huà) 紅球放大 綠球縮小
        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;
        
        // 更新方向 改變?nèi)齻€(gè)球的相對(duì)位置
        if (CGRectGetMinX(self.greenBall.frame) <= 0 || CGRectGetMaxX(self.redBall.frame) >= self.containerView.bounds.size.width) {
            // 切換為正向
            self.moveDirection = GKBallMoveDirectionPositive;
            // 正向運(yùn)動(dòng) 綠球在上 紅球在下
            [self.containerView bringSubviewToFront:self.greenBall];
            // 黑球放在綠球上面
            [self.greenBall addSubview:self.blackBall];
            // 重置動(dòng)畫(huà)
            [self resetAnimation];
        }
    }
}

具體代碼可在demo中的GKBallLoadingView中查看栓撞。

2遍膜、視頻加載動(dòng)畫(huà)

視頻加載

這個(gè)動(dòng)畫(huà)比較簡(jiǎn)單,首先以x軸為中心進(jìn)行縮放動(dòng)畫(huà)瓤湘,然后再修改的透明度即可瓢颅,主要代碼如下:

    // 創(chuàng)建動(dòng)畫(huà)組
    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    animationGroup.duration = GKLineLoadingDuration;
    animationGroup.beginTime = CACurrentMediaTime();
    animationGroup.repeatCount = MAXFLOAT;
    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    // x軸縮放動(dòng)畫(huà)(transform.scale是以view的中心點(diǎn)為中心開(kāi)始縮放的)
    CABasicAnimation *scaleAnimation = [CABasicAnimation animation];
    scaleAnimation.keyPath = @"transform.scale.x";
    scaleAnimation.fromValue = @(1.0f);
    scaleAnimation.toValue = @(1.0f * self.superview.frame.size.width);
    
    // 透明度漸變動(dòng)畫(huà)
    CABasicAnimation *alphaAnimation = [CABasicAnimation animation];
    alphaAnimation.keyPath = @"opacity";
    alphaAnimation.fromValue = @(1.0f);
    alphaAnimation.toValue = @(0.5f);
    
    animationGroup.animations = @[scaleAnimation, alphaAnimation];
    // 添加動(dòng)畫(huà)
    [self.layer addAnimation:animationGroup forKey:nil];

具體代碼可在demo中的GKLineLoadingView中查看。

3弛说、紅心點(diǎn)贊動(dòng)畫(huà)

紅心點(diǎn)贊

這個(gè)動(dòng)畫(huà)的主要是通過(guò)CAShapeLayer和貝賽爾曲線(xiàn)繪制三角形挽懦,循環(huán)創(chuàng)建6次在6個(gè)方向繪制三角形,并加入動(dòng)畫(huà)木人,然后進(jìn)行紅心的縮放動(dòng)畫(huà)信柿,主要代碼如下:

    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、雙擊點(diǎn)贊動(dòng)畫(huà)

雙擊點(diǎn)贊

這個(gè)動(dòng)畫(huà)主要是通過(guò)在- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法中根據(jù)觸摸的位置不停創(chuàng)建紅心醒第,并放大渔嚷、透明,然后銷(xiāo)毀稠曼,主要代碼如下:

- (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;
    
    // 隨機(jī)左右顯示
    int leftOrRight = arc4random() % 2;
    leftOrRight = leftOrRight ? leftOrRight : -1;
    imgView.transform = CGAffineTransformRotate(imgView.transform, M_PI / 9.0f * leftOrRight);
    [touch.view addSubview:imgView];
    
    // 出現(xiàn)的時(shí)候回彈一下
    __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中查看。

最后

上面提到的所有動(dòng)畫(huà)都可以在github上的demoGKDYVideo中查看漠吻,如果覺(jué)得不錯(cuò)量瓜,還請(qǐng)來(lái)個(gè)star!

贊賞

您的贊賞是對(duì)我最大的支持

微信贊賞
支付寶贊賞

參考

抖音點(diǎn)贊動(dòng)畫(huà)實(shí)現(xiàn)—iOS
iOS開(kāi)發(fā)_仿抖音點(diǎn)贊動(dòng)畫(huà)功能的實(shí)現(xiàn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市途乃,隨后出現(xiàn)的幾起案子榔至,更是在濱河造成了極大的恐慌,老刑警劉巖欺劳,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唧取,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡划提,警方通過(guò)查閱死者的電腦和手機(jī)枫弟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)鹏往,“玉大人淡诗,你說(shuō)我怎么就攤上這事∫谅模” “怎么了韩容?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)唐瀑。 經(jīng)常有香客問(wèn)我群凶,道長(zhǎng),這世上最難降的妖魔是什么哄辣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任请梢,我火速辦了婚禮,結(jié)果婚禮上力穗,老公的妹妹穿的比我還像新娘毅弧。我一直安慰自己,他們只是感情好当窗,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布够坐。 她就那樣靜靜地躺著,像睡著了一般崖面。 火紅的嫁衣襯著肌膚如雪元咙。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天嘶朱,我揣著相機(jī)與錄音蛾坯,去河邊找鬼。 笑死疏遏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播财异,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼倘零,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了戳寸?” 一聲冷哼從身側(cè)響起呈驶,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎疫鹊,沒(méi)想到半個(gè)月后袖瞻,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拆吆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年聋迎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枣耀。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡霉晕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捞奕,到底是詐尸還是另有隱情牺堰,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布颅围,位于F島的核電站伟葫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏院促。R本人自食惡果不足惜扒俯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望一疯。 院中可真熱鬧撼玄,春花似錦、人聲如沸墩邀。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)眉睹。三九已至荔茬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間竹海,已是汗流浹背慕蔚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留斋配,地道東北人孔飒。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓灌闺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親坏瞄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桂对,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 前言 今天給大家分享一下抖音的點(diǎn)贊動(dòng)畫(huà)的實(shí)現(xiàn), 廢話(huà)不多說(shuō)上圖 本篇文章主要包含技術(shù)點(diǎn): CAShapeLayer...
    iOS猿_員閱讀 13,759評(píng)論 7 50
  • text-align: center的作用是什么,作用在什么元素上鸠匀?能讓什么元素水平居中text-align屬性通...
    YangJeremy閱讀 632評(píng)論 0 50
  • 寫(xiě)作第二天 起床:6點(diǎn)鐘起床 天氣:晴 心情:興奮 任務(wù)清單 周目標(biāo)·完成進(jìn)度 學(xué)習(xí)·信息·閱讀 健康·飲食·鍛煉...
    愛(ài)生活_3b83閱讀 186評(píng)論 0 0