JWGiveLikeAnimation
描述:iOS 抖音点赞动画 收藏动画
git传送门
前言
最近项目中需要模仿抖音的点赞动画来应用到项目中,所以自己撸了一个动画,给同行们分享下,不喜勿喷。欢迎随时批评指正 QQ:38251725
实现思路
-
点赞动画
将点赞动画分解为4个部分
- 6个倒三角形从中心向外扩散,先缩放在放大
- 6个三角全部展开之后由内向外消失
- 心形点赞图片 从小扩大在收缩动画
- 波纹慢慢扩大至心型图片圆周,再慢慢消失
实现原理:
动画1、2:使用CAShapeLayer图层,UIBezierPath曲线绘制三角形。然后使用CAAnimationGroup来实现缩放和消失组合动画。
- (void)createTrigonsAnimtion { //三角形大小 for (int i = 0; i < 6; i++) { //绘制三角形的图层 CAShapeLayer * shapeLayer = [[CAShapeLayer alloc]init]; shapeLayer.position = _giveLikeView.center; shapeLayer.fillColor = self.shapeFillColor.CGColor; //三角形 UIBezierPath * startPath = [UIBezierPath bezierPath]; [startPath moveToPoint:CGPointMake(-2, _length)]; [startPath addLineToPoint:CGPointMake(2, _length)]; [startPath addLineToPoint:CGPointMake(0, 0)]; shapeLayer.path = startPath.CGPath; //旋转图层,形成圆形 //因为一共是6个,均等应该是反转60度 所以是M_PI/3 ,围绕Z轴旋转 shapeLayer.transform = CATransform3DMakeRotation(M_PI / 3 * i, 0, 0, 1); [self.layer addSublayer:shapeLayer]; //使用动画组来解决三角形 出现跟消失】 CAAnimationGroup * groupAnimation = [CAAnimationGroup animation]; groupAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; groupAnimation.duration = self.animationDurtion; groupAnimation.fillMode = kCAFillModeForwards; groupAnimation.removedOnCompletion = NO; CABasicAnimation * scaleAnimtion = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; //缩放时间占20% scaleAnimtion.duration = self.animationDurtion * 0.2; scaleAnimtion.fromValue = @(0); scaleAnimtion.toValue = @(1); //绘制三角形结束 一条直线 UIBezierPath * endPath = [UIBezierPath bezierPath]; [endPath moveToPoint:CGPointMake(-2, _length)]; [endPath addLineToPoint:CGPointMake(2, _length)]; [endPath addLineToPoint:CGPointMake(0, _length)]; CABasicAnimation * pathAnimtion = [CABasicAnimation animationWithKeyPath:@"path"]; pathAnimtion.beginTime = self.animationDurtion * 0.2; pathAnimtion.duration = self.animationDurtion * 0.8; pathAnimtion.fromValue = (__bridge id)startPath.CGPath; pathAnimtion.toValue = (__bridge id)endPath.CGPath; groupAnimation.animations = @[scaleAnimtion,pathAnimtion]; [shapeLayer addAnimation:groupAnimation forKey:nil]; } }
动画3: 心形图片放大缩小,使用UIView的帧动画,来设置每帧的动画。分2部分,一部分是放大一部分是恢复
[UIView animateKeyframesWithDuration:self.animationDurtion delay:0.0 options:UIViewKeyframeAnimationOptionLayoutSubviews animations:^{ /*参数1:关键帧开始时间 参数2:关键帧占用时间比例 参数3:到达该关键帧时的属性值 */ [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 * self.animationDurtion animations:^{ self.giveLikeView.transform = CGAffineTransformMakeScale(1.5, 1.5);; }]; [UIView addKeyframeWithRelativeStartTime:0.5 * self.animationDurtion relativeDuration:0.5 * self.animationDurtion animations:^{ self.giveLikeView.transform = CGAffineTransformIdentity; }]; } completion:^(BOOL finished) { self.userInteractionEnabled = YES; }];
动画4:波纹动画使用CAShapeLayer绘制一个圆圈,CAAnimationGroup组合使用 缩小、宽度变宽,再消失。
- (void)createCircleAnimation { //创建背景圆环 CAShapeLayer *circleLayer = [[CAShapeLayer alloc]init]; circleLayer.frame = self.bounds; //清空填充色 circleLayer.fillColor = [UIColor clearColor].CGColor; //设置画笔颜色 即圆环背景色 circleLayer.strokeColor = self.shapeFillColor.CGColor; circleLayer.lineWidth = 1; //设置画笔路径 UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0) radius:_length startAngle:- M_PI_2 endAngle:-M_PI_2 + M_PI * 2 clockwise:YES]; //path 决定layer将被渲染成何种形状 circleLayer.path = path.CGPath; [self.layer addSublayer:circleLayer]; //使用动画组来解决圆圈从小到大 -->消失 CAAnimationGroup * groupAnimation = [CAAnimationGroup animation]; groupAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; NSTimeInterval groupDurtion = self.animationDurtion * 0.8; groupAnimation.duration = groupDurtion; groupAnimation.fillMode = kCAFillModeForwards; groupAnimation.removedOnCompletion = NO; CABasicAnimation * scaleAnimtion = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; //放大时间占80% scaleAnimtion.duration = groupDurtion * 0.8; scaleAnimtion.fromValue = @(0); scaleAnimtion.toValue = @(1); CABasicAnimation * widthStartAnimtion = [CABasicAnimation animationWithKeyPath:@"lineWidth"]; widthStartAnimtion.beginTime = 0; widthStartAnimtion.duration = groupDurtion * 0.8; widthStartAnimtion.fromValue = @(1); widthStartAnimtion.toValue = @(3); CABasicAnimation * widthEndAnimtion = [CABasicAnimation animationWithKeyPath:@"lineWidth"]; widthEndAnimtion.beginTime = groupDurtion * 0.8; widthEndAnimtion.duration = groupDurtion * 0.2; widthEndAnimtion.fromValue = @(3); widthEndAnimtion.toValue = @(0); groupAnimation.animations = @[scaleAnimtion,widthStartAnimtion,widthEndAnimtion]; [circleLayer addAnimation:groupAnimation forKey:@"circleLayerAnimtion"]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(groupDurtion * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [circleLayer removeAnimationForKey:@"circleLayerAnimtion"]; [circleLayer removeFromSuperlayer]; }); }
-
取消点赞动画
取消点赞动画分解,点赞图片由外向内慢慢消失。
[self bringSubviewToFront:_giveLikeView]; _giveLikeView.transform = CGAffineTransformMakeScale(1.1, 1.1); [UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{ self.giveLikeView.transform = CGAffineTransformMakeScale(0.1, 0.1); } completion:^(BOOL finished) { self.giveLikeView.hidden = YES; self.giveLikeView.transform = CGAffineTransformMakeScale(1, 1); self.userInteractionEnabled = YES; }];
总结
以上就是整个动画的分解原理。主要是使用的Shaperlayer图层 贝塞尔绘制图形,使用动画组还合成动画的实现。