AYProcessView啟動動畫實(shí)現(xiàn)

前言

  • 前段時間看到一個挺有趣的動畫效果隔心,于是就想著實(shí)現(xiàn)一下,順便練下手尚胞,這里是第一篇教程硬霍,介紹了啟動動畫的制作,示例代碼放在這里笼裳,完整的demo會在最后一篇教程放出

動畫引擎的選擇

  • 使用Facebook開源的pop以及iOS自帶的CoreAnimation

實(shí)現(xiàn)指示牌開始階段的動畫

  • 實(shí)現(xiàn)思路是使用一個CALayer作為容器唯卖,也就是containerLayer粱玲,在容器當(dāng)中再放置兩個layer,一個矩形rectLayer與一個三角形triLayer組成一個指示牌拜轨,形變的動畫由容器內(nèi)部的layer來執(zhí)行密幔,而位移的動畫由containerLayer來執(zhí)行

  • 具體的代碼如下:

    - (void)initRectLayer{
      self.rectLayer = [CALayer layer];
      self.rectLayer.backgroundColor = [UIColor colorWithWhite:1 alpha:1].CGColor;
      self.rectLayer.position = CGPointMake(self.containerLayer.frame.size.width/2,       self.containerLayer.frame.size.height/4);
      self.rectLayer.bounds = CGRectMake(0, 0, 24, 30);
      self.rectLayer.cornerRadius = 2.f;
      [self.containerLayer addSublayer:self.rectLayer];
    }
    - (void)initTriLayer{
      self.triLayer = [CAShapeLayer layer];
      [self.containerLayer addSublayer:self.triLayer];
      UIBezierPath *bottomBezierPath = [UIBezierPath bezierPath];
      self.triLayer.position = CGPointMake(self.containerLayer.frame.size.width/2-20, self.containerLayer.frame.size.height/70);
      [bottomBezierPath moveToPoint:CGPointMake(0, 28)];
      [bottomBezierPath addLineToPoint:CGPointMake(40, 28)];
      [bottomBezierPath addLineToPoint:CGPointMake(20, 50)];
      [bottomBezierPath closePath];
      self.triLayer.path = bottomBezierPath.CGPath;
      self.triLayer.fillColor = [UIColor whiteColor].CGColor;
    }
    - (void)initContainerLayer{
      self.containerLayer = [CALayer layer];
      self.containerLayer.position = CGPointMake(self.worksheetView.frame.size.width/2, self.worksheetView.frame.size.height/2);
      self.containerLayer.bounds = CGRectMake(0, 0, 60, 60);
      self.containerLayer.backgroundColor = [UIColor clearColor
                                       ].CGColor;
      [self.worksheetView.layer addSublayer:self.containerLayer];
    }
    - (void)rectLayerAnimation{
       POPBasicAnimation *topScaleAnim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerSize];
       topScaleAnim.toValue = [NSValue valueWithCGSize:CGSizeMake(40, 25)];
       topScaleAnim.duration = 1;
       POPBasicAnimation *topPositionAnim = [POPBasicAnimation    animationWithPropertyNamed:kPOPLayerPosition];
       topPositionAnim.toValue = [NSValue valueWithCGPoint:CGPointMake(24, 40)];
       topPositionAnim.duration = 0.5; 
       POPBasicAnimation *topCornerAnim = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerCornerRadius];
       topCornerAnim.toValue = @3.f;
       topCornerAnim.duration = 0.5;
       POPSpringAnimation *shakeAnim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerRotation];
      shakeAnim.toValue = @(0.5);
      shakeAnim.springBounciness = 20;    
      [self.rectLayer pop_addAnimation:topScaleAnim forKey:@"IndiReadyStyleTopScaleAnim"];
      [self.rectLayer pop_addAnimation:topCornerAnim forKey:@"IndiReadyStyleTopCornerAnim"];
    }
    - (void)triLayerAnimation{
        POPBasicAnimation *bottonScaleAnimation = [POPBasicAnimation     animationWithPropertyNamed:kPOPLayerScaleXY];
        bottonScaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(0.25, 0.25)];
        bottonScaleAnimation.duration = 0.5;
        POPBasicAnimation *bottonPosition1stAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPosition];
        bottonPosition1stAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(self.worksheetView.frame.size.width/2-50, self.worksheetView.frame.size.height/2-50)];
        bottonPosition1stAnimation.duration = 0.5;    
        POPBasicAnimation *bottonPositionAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPosition];
        bottonPositionAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(self.triLayer.position.x + 15, self.triLayer.position.y+19)];
        bottonPositionAnimation.duration = 0.5;    
        [self.triLayer pop_addAnimation:bottonScaleAnimation forKey:@"IndiReadyStyleBottomScaleAnim"];
        [self.triLayer pop_addAnimation:bottonPositionAnimation forKey:@"IndiReadyStyleBottomPositionYAnim"];
    }
     - (void)containerLayerAnimation{
        CGPoint originPoint = self.containerLayer.position;
        POPCustomAnimation *customAnimation = [POPCustomAnimation animationWithBlock:^BOOL(id target, POPCustomAnimation *animation) {
        self.containerLayer.position = CGPointMake(self.containerLayer.position.x - 3, self.containerLayer.position.y - 3);
        BOOL downSwitch;
        if (self.containerLayer.position.x - originPoint.x <= -80) {
            downSwitch = YES;
        }
        if (downSwitch) {
            self.containerLayer.position = CGPointMake(self.containerLayer.position.x, self.containerLayer.position.y+10);
        }
        if (self.containerLayer.position.y >= originPoint.y + 41) {
            return NO;
        }else{
            return YES;
        }
      }];
      [self.containerLayer pop_addAnimation:customAnimation forKey:@"IndiReadyStyleOutSizeLayerAnim"];
    }
    

實(shí)現(xiàn)開始階段圓變成線的效果

  • 這里實(shí)際上分成兩個階段,一個由實(shí)心圓開始變化撩轰,從實(shí)心圓開始變化成一個圓環(huán)最后消失胯甩;消失的一瞬間替換成貝塞爾曲線,后面就是對貝塞爾曲線進(jìn)行操縱了

  • 先說從實(shí)心圓變成圓環(huán)的效果堪嫂,這個只需要借助pop對圓的borderwidth屬性進(jìn)行動畫便可偎箫,非常簡單

    - (void)innerCircleLayerAnimation{
       POPBasicAnimation *circleLayerBorderWidthAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerBorderWidth];
       circleLayerBorderWidthAnimation.toValue = @(2);
       circleLayerBorderWidthAnimation.duration = 1.f;
       [self.innerCircleLayer pop_addAnimation:circleLayerBorderWidthAnimation forKey:@"IndiReadyStyleInnerLayerBorderWidthAnim"];
    }
    
  • 接下來是圓變成線的效果,消失之后的圓環(huán)會被貝塞爾曲線所取代皆串,實(shí)際上是由四段貝塞爾曲線拼接成的圓淹办,只要畫出貝塞爾曲線幾個關(guān)鍵的變形狀態(tài)便可以使用CoreAnimation來制作過渡的變化效果,最終實(shí)現(xiàn)效果如下:


  • 需要畫出貝塞爾曲線展開過程的兩個關(guān)鍵狀態(tài)恶复,一個是展開到一半的狀態(tài)怜森,另一個是完全展開成一條直線的狀態(tài)

  • 展開成一半的貝塞爾曲線效果如圖:


  • 展開成一條直線效果如圖:


  • 關(guān)鍵的代碼如下:

    - (void)initFancyPath{
        self.outSizeRectLayer = [CALayer layer];
        self.outSizeRectLayer.position = CGPointMake(self.worksheetView.frame.size.width/2,self.worksheetView.frame.size.height/2);
        self.outSizeRectLayer.bounds = CGRectMake(0, 0, 100, 100);
        self.outSizeRectLayer.backgroundColor = [UIColor clearColor].CGColor;
        [self.worksheetView.layer addSublayer:self.outSizeRectLayer];
    
        CGFloat originX = self.containerLayer.bounds.origin.x;
        CGFloat originY = self.containerLayer.bounds.origin.y;
        CGFloat originWidth = 100;
        CGFloat originHeight = 100;
    
        self.rectCenter = CGPointMake(originX + originWidth/2, originY + originHeight/2);
        CGFloat extraX = 0;
        CGFloat extraY = 0;
        CGFloat offset = originWidth / 3.6;
    
        self.pointA = CGPointMake(self.rectCenter.x + extraX, originY + extraY);
        self.pointB = CGPointMake(originX + originWidth + extraX, self.rectCenter.y + extraY);
        self.pointC = CGPointMake(self.rectCenter.x + extraX, originY + originHeight + extraY);
        self.pointD = CGPointMake(originX + extraX, self.rectCenter.y + extraY);
        self.pointE = CGPointMake(self.rectCenter.x + extraX, originY + extraY);
    
        self.c1 = CGPointMake(self.pointA.x + offset, self.pointA.y);
        self.c2 = CGPointMake(self.pointB.x, self.pointB.y - offset);
    
        self.c3 = CGPointMake(self.pointB.x, self.pointB.y + offset);
        self.c4 = CGPointMake(self.pointC.x + offset, self.pointC.y);
    
        self.c5 = CGPointMake(self.pointC.x - offset, self.pointC.y);
        self.c6 = CGPointMake(self.pointD.x, self.pointD.y + offset);
    
        self.c7 = CGPointMake(self.pointD.x, self.pointD.y - offset);
        self.c8 = CGPointMake(self.pointA.x - offset, self.pointA.y);
    
        self.fancyLine = [UIBezierPath bezierPath];
        self.fancyShape = [CAShapeLayer layer];
        [self.fancyLine moveToPoint: self.pointA];
        [self.fancyLine addCurveToPoint:self.pointB controlPoint1:self.c1 controlPoint2:self.c2];
        [self.fancyLine addCurveToPoint:self.pointC controlPoint1:self.c3 controlPoint2:self.c4];
        [self.fancyLine addCurveToPoint:self.pointD controlPoint1:self.c5 controlPoint2:self.c6];
        [self.fancyLine addCurveToPoint:self.pointE controlPoint1:self.c7 controlPoint2:self.c8];
        [self.fancyLine closePath];
    
        self.fancyShape.path = self.fancyLine.CGPath;
        self.fancyShape.position = CGPointMake(self.rectCenter.x, self.rectCenter.y);
        self.fancyShape.bounds = CGPathGetBoundingBox(self.fancyShape.path);
        self.fancyShape.strokeColor = [UIColor blackColor].CGColor;
        self.fancyShape.fillColor = [UIColor clearColor].CGColor;
        self.fancyShape.lineWidth = 3.0;
        [self.outSizeRectLayer addSublayer:self.fancyShape];
      }
    - (void)bezierPathAnimation{
        CGPoint pointAm = CGPointMake(self.pointA.x + 90, self.pointA.y);
        CGPoint pointEm = CGPointMake(self.pointE.x - 90, self.pointE.y);
        CGPoint pointBm = CGPointMake(self.pointB.x, self.pointB.y);
        CGPoint pointDm = CGPointMake(self.pointD.x, self.pointD.y);
        CGPoint c1m = CGPointMake(self.c1.x + 20, self.c1.y + 10);
        CGPoint c2m = CGPointMake(self.c2.x, self.c2.y + 10);
        CGPoint c7m = CGPointMake(self.c7.x, self.c7.y + 10);
        CGPoint c8m = CGPointMake(self.c8.x - 20, self.c8.y + 10);
    
        UIBezierPath *crazyPath = [UIBezierPath bezierPath];
        [crazyPath moveToPoint:pointAm];
        [crazyPath addCurveToPoint:pointBm controlPoint1:c1m controlPoint2:c2m];
        [crazyPath addCurveToPoint:self.pointC controlPoint1:self.c3 controlPoint2:self.c4];
        [crazyPath addCurveToPoint:pointDm controlPoint1:self.c5 controlPoint2:self.c6];
        [crazyPath addCurveToPoint:pointEm controlPoint1:c7m controlPoint2:c8m];
    
        self.fancyShape.path = crazyPath.CGPath;
        CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"];
        morph.duration = 0.3;
        morph.delegate = self;
        morph.toValue = (id)crazyPath;
        [self.fancyShape addAnimation:morph forKey:nil];
      }
    
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
        CGPoint pointAfin = CGPointMake(self.pointA.x + self.worksheetView.frame.size.width/2 - 10, self.pointA.y + 100);
        CGPoint pointBfin = CGPointMake(self.pointB.x, self.pointB.y + 50);
        CGPoint pointCfin = CGPointMake(self.pointC.x,self.pointC.y);
        CGPoint pointDfin = CGPointMake(self.pointD.x, self.pointD.y + 50);
        CGPoint pointEfin = CGPointMake(self.pointE.x - self.worksheetView.frame.size.width/2 + 10, self.pointE.y + 100);
      
        CGPoint c1fin = CGPointMake(self.c1.x + 100, self.c1.y + 100);
        CGPoint c2fin = CGPointMake(self.c2.x + 80, self.c2.y + 50 + 100/3.6);
        CGPoint c3fin = CGPointMake(self.c3.x - 5, self.c3.y + 50 - 100/3.6);
        CGPoint c4fin = CGPointMake(self.c4.x, self.c4.y);
        CGPoint c5fin = CGPointMake(self.c5.x, self.c5.y);
        CGPoint c6fin = CGPointMake(self.c6.x + 5, self.c6.y + 50 - 100/3.6);
        CGPoint c7fin = CGPointMake(self.c7.x - 80, self.c7.y + 50 + 100/3.6);
        CGPoint c8fin = CGPointMake(self.c8.x - 100, self.c8.y + 100);
    
        UIBezierPath *lineFinalPath = [UIBezierPath bezierPath];
        [lineFinalPath moveToPoint:pointAfin];
        [lineFinalPath addCurveToPoint:pointBfin controlPoint1:c1fin controlPoint2:c2fin];
        [lineFinalPath addCurveToPoint:pointCfin controlPoint1:c3fin controlPoint2:c4fin];
        [lineFinalPath addCurveToPoint:pointDfin controlPoint1:c5fin controlPoint2:c6fin];
        [lineFinalPath addCurveToPoint:pointEfin controlPoint1:c7fin controlPoint2:c8fin];
    
        self.fancyShape.path = lineFinalPath.CGPath;
        CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"];
        morph.duration = 0.3;
        morph.toValue = (id)lineFinalPath;
        [self.fancyShape addAnimation:morph forKey:nil];
    }
    
  • 曲線的坐標(biāo)計(jì)算借助了一個外接矩形進(jìn)行輔助定位

  • ok,第一篇教程就到此結(jié)束了谤牡,第二篇將介紹下載過程指示牌移動的動畫

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末副硅,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子翅萤,更是在濱河造成了極大的恐慌恐疲,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件套么,死亡現(xiàn)場離奇詭異培己,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胚泌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門省咨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人玷室,你說我怎么就攤上這事零蓉。” “怎么了阵苇?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵壁公,是天一觀的道長。 經(jīng)常有香客問我绅项,道長,這世上最難降的妖魔是什么比肄? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任快耿,我火速辦了婚禮囊陡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掀亥。我一直安慰自己撞反,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布搪花。 她就那樣靜靜地躺著遏片,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撮竿。 梳的紋絲不亂的頭發(fā)上吮便,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機(jī)與錄音幢踏,去河邊找鬼髓需。 笑死,一個胖子當(dāng)著我的面吹牛房蝉,可吹牛的內(nèi)容都是我干的僚匆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼搭幻,長吁一口氣:“原來是場噩夢啊……” “哼咧擂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起檀蹋,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤屋确,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后续扔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體攻臀,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年纱昧,在試婚紗的時候發(fā)現(xiàn)自己被綠了刨啸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡识脆,死狀恐怖设联,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情灼捂,我是刑警寧澤离例,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站悉稠,受9級特大地震影響宫蛆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜的猛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一耀盗、第九天 我趴在偏房一處隱蔽的房頂上張望想虎。 院中可真熱鬧,春花似錦叛拷、人聲如沸舌厨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽裙椭。三九已至,卻和暖如春署浩,著一層夾襖步出監(jiān)牢的瞬間揉燃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工瑰抵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留你雌,地道東北人。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓二汛,卻偏偏與公主長得像婿崭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子肴颊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

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