最近在學(xué)習(xí)iOS的動(dòng)畫效果,做的一些小demo記錄自己的學(xué)習(xí)過程,也和大家分享一下自己的做法泣崩,如果有不周到的地方請(qǐng)大神們不吝賜教伊群。
今天給大家分享一下自己做的仿照抖音點(diǎn)贊的一個(gè)小動(dòng)畫。
一.效果展示
主要涉及了三個(gè)過程:煙花散開的過程影兽、紅心順時(shí)針旋轉(zhuǎn)出現(xiàn)揭斧、紅線逆時(shí)針旋轉(zhuǎn)縮小消失。
旋轉(zhuǎn)和縮小是比較簡(jiǎn)單的過程(不能了解的小伙伴可以下載demo自行查看),我們今天主要分析煙花散開的效果峻堰。
二.效果分析
主要包含的技術(shù):
1讹开、CAShapeLayer和UIBezierPath 繪制。
2捐名、CAAnimationGroup組合動(dòng)畫萧吠。
仔細(xì)觀察慢動(dòng)畫,發(fā)現(xiàn)主題是一個(gè)三角形,旋轉(zhuǎn)60度繪制6個(gè)。
動(dòng)畫的過程大概是:
a.先縮放動(dòng)畫從0到1的過程 執(zhí)行時(shí)間duration * 0.2
b.然后執(zhí)行路徑動(dòng)畫的起始點(diǎn)是原點(diǎn)(0桐筏,0)消失點(diǎn)在三角形的底邊(width,0)開始時(shí)間是duration * 0.2,執(zhí)行時(shí)長(zhǎng)是duration * 0.8.
路徑動(dòng)畫的執(zhí)行過程大概是:
三拇砰、結(jié)合代碼分析
首先封裝了一個(gè)UIView實(shí)現(xiàn)動(dòng)畫效果:YPGiveLikeButton梅忌。YPGiveLikeButton包含兩個(gè)UIImageView實(shí)現(xiàn)圖片顯示和動(dòng)畫效果。具體可以參考demo,這里只介紹核心代碼除破。
1.創(chuàng)建繪制三角形的layer
CAShapeLayer *layer = [CAShapeLayer layer];
layer.position = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5);
layer.fillColor = [UIColor redColor].CGColor;
layer.strokeColor = [UIColor clearColor].CGColor;
layer.anchorPoint = CGPointMake(0.5, 0.5);
for循環(huán)創(chuàng)建6個(gè)這樣的小三角
CGFloat length = 4;
CGFloat width = 30;
for (int i = 0; i < 6; i++) {
CAShapeLayer *layer = [CAShapeLayer layer];
layer.position = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5);
layer.fillColor = [UIColor redColor].CGColor;
layer.strokeColor = [UIColor clearColor].CGColor;
//...代碼塊1
//...代碼塊2
//...代碼塊3
//...代碼塊4
}
創(chuàng)建6個(gè)layer實(shí)例,并利用貝塞爾曲線繪制小三角形牧氮。
在...代碼塊1
位置加入
UIBezierPath *startPath = [UIBezierPath bezierPath];
[startPath moveToPoint:CGPointMake((- length) * 0.5, -width)];
[startPath addLineToPoint:CGPointMake((length) * 0.5, -width)];
[startPath addLineToPoint:CGPointMake(0, 0)];
[startPath addLineToPoint:CGPointMake((- length) * 0.5, -width)];
將貝塞爾曲線作為layer的path,通過旋轉(zhuǎn)將6個(gè)小三角圍繞layer的中心鋪開。
在...代碼塊2
位置加入
layer.path = startPath.CGPath;
layer.transform = CATransform3DMakeRotation(M_PI / 3.0f * i, 0.0, 0.0, 1.0);
[self.layer addSublayer:layer];
接著創(chuàng)建一個(gè)收縮的動(dòng)畫,開始時(shí)間是CACurrentMediaTime(),動(dòng)畫時(shí)長(zhǎng)是duration * 0.2,設(shè)置動(dòng)畫是長(zhǎng)是1s,那么伸縮動(dòng)畫就是0.2s.
在...代碼3
位置加入
//伸縮動(dòng)畫
CABasicAnimation *scralAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scralAnimation.fromValue = @(0.0);;
scralAnimation.toValue = @(1.0);
scralAnimation.duration = duration * 0.2;
接著創(chuàng)建一個(gè)小三角消失的動(dòng)畫,動(dòng)畫的開始時(shí)間是伸縮動(dòng)畫結(jié)束以后,也就是CACurrentMediaTime() + duration * 0.2,動(dòng)畫是時(shí)長(zhǎng)是duration * 0.8.然后創(chuàng)建一個(gè)動(dòng)畫組瑰枫,將伸縮動(dòng)畫和小三角的消失動(dòng)畫加入動(dòng)畫組中踱葛。
在...代碼4
位置加入
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
pathAnimation.fromValue = (__bridge id)layer.path;
pathAnimation.toValue = (__bridge id)endPath.CGPath;
pathAnimation.beginTime = duration * 0.2;
pathAnimation.duration = duration * 0.8;
CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.animations = @[pathAnimation,scralAnimation];
groupAnimation.fillMode = kCAFillModeForwards;
groupAnimation.duration = duration;
groupAnimation.removedOnCompletion = NO;//完成后是否移除
groupAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
groupAnimation.delegate = self;
[layer addAnimation:groupAnimation forKey:@"groupAnimation"];
設(shè)置了groupAnimation.delegate = self;
在動(dòng)畫結(jié)束的時(shí)候?qū)⒓虞dself.layer
上的6個(gè)layer清除掉,避免用戶反復(fù)點(diǎn)贊造成sublayer過多光坝。
到此煙花散開的動(dòng)畫就結(jié)束了尸诽。除此之外,點(diǎn)贊的時(shí)候還可以加上一個(gè)給??旋轉(zhuǎn)的動(dòng)畫:
旋轉(zhuǎn)動(dòng)畫結(jié)束前,禁用選中的點(diǎn)擊事件盯另,防止動(dòng)畫結(jié)束前用戶多次點(diǎn)擊性含。動(dòng)畫結(jié)束以后將點(diǎn)擊事件放開。
self.selected = YES;
self.afterImageView.userInteractionEnabled = NO;
CAKeyframeAnimation *rotateAnima = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
rotateAnima.values = @[@0.0, @(M_PI * 0.15), @(0.0)];
rotateAnima.duration = duration * 0.5;
rotateAnima.repeatCount = 1;
rotateAnima.beginTime = CACurrentMediaTime();
rotateAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
rotateAnima.delegate = self;
[self.afterImageView.layer addAnimation:rotateAnima forKey:@"rotationAnimation"];
注意
:取消點(diǎn)贊的動(dòng)畫鸳惯,是用了UIView的動(dòng)畫代碼如下:
self.beforeImageView.hidden = NO;
[UIView animateWithDuration:0.35f delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
self.afterImageView.transform = CGAffineTransformScale(CGAffineTransformMakeRotation(-M_PI_4), 0.1f, 0.1f);
}completion:^(BOOL finished) {
self.selected = NO;
self.afterImageView.transform = CGAffineTransformMakeScale(1.0f, 1.0f);
}];
四商蕴、總結(jié)
以上是模仿抖音點(diǎn)贊動(dòng)畫、取消點(diǎn)贊動(dòng)畫的核心代碼芝发。如果需要demo
可以去demo地址