iOS实现抖音点赞动画效果

本文实例为大家分享了iOS实现抖音点赞动画的具体代码,供大家参考,具体内容如下

1. 概述

最近看到抖音点赞爱心的动画效果比较好,出于好奇,自己也研究仿照动画效果写了一个,不喜欢的朋友可不要喷我噢!!!

话不多说,先来看一下执行效果。

2. 动画分析

上面的示例效果有点快,现在来看一个慢的,然后在分析动画组成。

这回看清楚了吧,哈哈。

2.1 动画过程分析

咱们就以10秒的点赞动画来分析一下:

点赞的时候:

1、点击的时候,白色爱心逐渐变小到一定程度,然后变成红色爱心。(3秒)

2、红色爱心慢慢变大,最终有个缓冲动画,然后恢复原尺寸。(7秒)

3、在红色爱心变大的时候,有一个红色的圆环逐渐变大,圆环宽度由小变大,再变小消失。(5秒)

4、在红色爱心变大的时候,还有6个环绕爱心的三角形,三角形由小变大,再变小消失。(7秒)

5、注意,2、3、4的动画是在1动画结束后同时执行的,即延迟3秒再执行。

取消点赞的时候:

1、点击后红色爱心逐渐变小。

2、变小后,设置不可见,并恢复原尺寸。

2.2 代码实现原理分析

1、自定义一个UIView,并添加两个UIImageView,分别显示红色爱心和白色爱心,红色爱心在白色爱心上面,并设置红色爱心不可见。

2、给UIView添加单击手势。

3、点击时判断是点赞还是取消点赞,如果是点赞:

4、用两个UIView自带的动画,将白色ImageView的transform变小,变小后不可见,然后设置红色ImageView的transform变大,变大后白色ImageView的transform变回原尺寸。

5、通过贝塞尔曲线和CAShapeLayer绘制圆环,并给圆环添加动画组CAAnimationGroup,动画组中添加了一个基础动画CABasicAnimation(将圆环从小变大)和一个关键帧动画CAKeyframeAnimation(将圆环宽度由小变大再变小消失)

6、通过贝塞尔曲线和CAShapeLayer循环绘制6个三角形,并通过CATransform3DMakeRotation旋转6个三角形,使其环绕爱心一周。

7、给每个三角形添加一个关键帧动画CAKeyframeAnimation(将三角形由小变大再变小消失)

8、如果是取消点赞,比较简单,逐渐将红色爱心变小,然后设置不可见,白色爱心自然就显示出来了。

9、在动画执行过程中,关闭用户交互,待动画结束,再打开用户交互。

分析的有些简单,只是提供一种思路,没有什么比看代码更直接的了,来吧!

3. 全部代码

代码中添加了很多的注释,方便理解。

import UIKit

public class LikeView: UIView {

// 红色爱心视图

fileprivate var likeImageView = UIImageView()

// 白色爱心视图

fileprivate var unLikeImageView = UIImageView()

// true: 点赞, false:取消点赞

fileprivate var isLike: Bool = false

// 动画时长,可设置

public var duration: CFTimeInterval = 0.5

override init(frame: CGRect) {

super.init(frame: frame)

setupUI()

}

required init?(coder: NSCoder) {

super.init(coder: coder)

setupUI()

}

fileprivate func setupUI() {

// 添加白色爱心视图

unLikeImageView.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)

unLikeImageView.image = UIImage(named: "icon_like_before")

addSubview(unLikeImageView)

// 添加红色爱心视图,并设置不可看。切记红色爱心在在白色爱心的上面。

likeImageView.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)

likeImageView.image = UIImage(named: "icon_like_after")

likeImageView.alpha = 0

addSubview(likeImageView)

// 添加单击手势

let tap = UITapGestureRecognizer(target: self, action: #selector(tapLikeAction))

self.addGestureRecognizer(tap)

}

// 点击事件

@objc fileprivate func tapLikeAction() {

// 点击的时候停止交互,以免反复点击。

self.isUserInteractionEnabled = false

isLike = !isLike

// 点赞

if isLike {

// 设置红色爱心不可见

likeImageView.alpha = 0

// 将红色爱心缩小至原来0.2倍。

self.likeImageView.transform = CGAffineTransform(scaleX: 0.2, y: 0.2)

/* 添加动画, 使白色爱心变小,红色爱心变大,此过程占用全部动画时长。*/

UIView.animate(withDuration: duration * 0.3, delay: 0, options: .curveEaseInOut) { [weak self] in

// 将白色爱心逐渐变小至0.2倍,

self?.unLikeImageView.transform = CGAffineTransform(scaleX: 0.2, y: 0.2)

} completion: { [weak self] (finished) in

// 设置红色爱心可见,此时是0.2倍大小。

self?.likeImageView.alpha = 1

let duration = self?.duration ?? 0.5

// 白色爱心变小后,继续操作红色爱心

UIView.animate(withDuration: duration * 0.7, delay: 0.1, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.8, options: .curveEaseInOut) {

// 将红色爱心恢复原大小

self?.likeImageView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)

} completion: { (finished) in

// 红色爱心变大后,恢复白色爱心的尺寸,开启用户交互。

self?.unLikeImageView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)

self?.isUserInteractionEnabled = true

}

}

//***************** 以下是圆环动画,在红色爱心变大的时候执行。******************//

// 小圆环路径

let circleStartPath = UIBezierPath(arcCenter: likeImageView.layer.position, radius: self.bounds.size.width / 6, startAngle: 0, endAngle: CGFloat(2*Double.pi), clockwise: true)

// 大圆环路径

let radius = sqrt(powf(Float(self.bounds.size.width), 2) + powf(Float(self.bounds.size.height), 2))/2

let circleEndPath = UIBezierPath(arcCenter: likeImageView.layer.position, radius: CGFloat(radius), startAngle: 0, endAngle: CGFloat(2*Double.pi), clockwise: true)

// 创建圆环图层,用于显示圆环。

let circleLayer = CAShapeLayer()

circleLayer.strokeColor = UIColor.red.cgColor

circleLayer.fillColor = UIColor.clear.cgColor

self.layer.insertSublayer(circleLayer, below: self.likeImageView.layer)

// 计算圆环图层的偏移时间

var currentTimeInSuper = self.layer.convertTime(CACurrentMediaTime(), from: nil)

var currentTimeLocal = circleLayer.convertTime(currentTimeInSuper, from: self.layer)

// 设置圆环动画组执行时间

let circleGroupDuration = duration * 0.5

// 圆环动画组

let circleGroup = CAAnimationGroup()

circleGroup.duration = circleGroupDuration

// 圆环动画组开始时间,此开始时间正好是白色爱心变小后,红色爱心开始变大时。

circleGroup.beginTime = currentTimeLocal + duration * 0.3

// 设置圆环路径变化动画

let circlePathAnimation = CABasicAnimation(keyPath: "path")

circlePathAnimation.fromValue = circleStartPath.cgPath

circlePathAnimation.toValue = circleEndPath.cgPath

// 设置圆环宽度变化动画,先变大,再变小。

let circleLineWidthAnimation = CAKeyframeAnimation(keyPath: "lineWidth")

circleLineWidthAnimation.values = [1.0, 4.0, 0.3]

circleLineWidthAnimation.keyTimes = [0.0, 0.7, 0.9]

// 将圆环的两个动画添加到动画组。

circleGroup.animations = [circlePathAnimation, circleLineWidthAnimation]

// 将动画添加到圆环图层。

circleLayer.add(circleGroup, forKey: nil)

//**********************************************************************//

//***************** 以下是周围6个三角形放射动画,在红色爱心变大的时候执行。******************//

// 循环创建三角形图层,并添加动画效果

for i in 0..<6 {

// 三角形的高

let height = self.bounds.size.height / 2 + 12

// 三角形底边长

let width = self.bounds.size.width / 10

// 绘制一个起始三角形路径

let triangleStartPath = UIBezierPath()

triangleStartPath.move(to: .zero)

triangleStartPath.addLine(to: CGPoint(x: -1, y: -1))

triangleStartPath.addLine(to: CGPoint(x: 1, y: -1))

triangleStartPath.close()

// 绘制一个完全展开的三角形路径

let triangleMiddlePath = UIBezierPath()

triangleMiddlePath.move(to: .zero)

triangleMiddlePath.addLine(to: CGPoint(x: -width/2, y: -height))

triangleMiddlePath.addLine(to: CGPoint(x: width/2, y: -height))

triangleMiddlePath.close()

// 绘制一个终了三角形路径

let triangleEndPath = UIBezierPath()

triangleEndPath.move(to: CGPoint(x: 0, y: -height))

triangleEndPath.addLine(to: CGPoint(x: -width/2, y: -height))

triangleEndPath.addLine(to: CGPoint(x: width/2, y: -height))

triangleEndPath.close()

// 绘制三角形图层

let shapeLayer = CAShapeLayer()

// 设置图层中心位置,很重要。

shapeLayer.position = self.likeImageView.layer.position

shapeLayer.fillColor = UIColor.red.cgColor

// 将图层进行旋转。

shapeLayer.transform = CATransform3DMakeRotation(CGFloat(Double.pi/3) * CGFloat(i), 0, 0, 1)

self.layer.insertSublayer(shapeLayer, below: circleLayer)

// 计算三角形图层的偏移时间

currentTimeInSuper = self.layer.convertTime(CACurrentMediaTime(), from: nil)

currentTimeLocal = shapeLayer.convertTime(currentTimeInSuper, from: self.layer)

// 设置三角形的动画,由小变大再变小。

let trianglePathAnimation = CAKeyframeAnimation(keyPath: "path")

trianglePathAnimation.values = [triangleStartPath.cgPath, triangleMiddlePath.cgPath, triangleEndPath.cgPath]

trianglePathAnimation.keyTimes = [0.0, 0.3, 0.7]

trianglePathAnimation.duration = duration * 0.7

trianglePathAnimation.beginTime = currentTimeLocal + duration * 0.3

shapeLayer.add(trianglePathAnimation, forKey: nil)

}

//**********************************************************************//

}else {

// 取消点赞

// 1. 将红色爱心逐渐缩小至原来的0.1倍,然后设置为不可见并恢复原尺寸大小。

UIView.animate(withDuration: duration * 0.3, delay: 0, options: .curveEaseInOut) { [weak self] in

self?.likeImageView.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)

} completion: { [weak self] (finished) in

self?.likeImageView.alpha = 0

self?.likeImageView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)

self?.isUserInteractionEnabled = true

}

}

}

}

LikeView即是自定义的点赞视图,可纯代码创建,也可通过xib创建,同时支持设置动画执行时间duration。

调用的地方:

class ViewController: UIViewController {

override func viewDidLoad() {

super.viewDidLoad()

view.backgroundColor = UIColor.black

// 设置一个0.5秒的动画

let likeView1 = LikeView(frame: CGRect(x: 110, y: 300, width: 50, height: 50))

likeView1.duration = 0.5

self.view.addSubview(likeView1)

// 设置一个10秒的动画

let likeView2 = LikeView(frame: CGRect(x: 240, y: 300, width: 50, height: 50))

likeView2.duration = 10

self.view.addSubview(likeView2)

}

}

执行效果:

4. 结束语

代码中主要用到了:UIView基础动画、CGAffineTransform、CATransform3D、UIBezierPath、CAShapeLayer、CAKeyframeAnimation、CABasicAnimation、CAAnimationGroup,另外还有beginTime的计算,也算是个小重点了。

以上只是仿照抖音点赞动画实现的功能,代码不多,但也不少,不知道抖音是具体怎么实现的,如果有什么不对的地方,或者可优化的地方,还请路过的朋友多多指点。

以上是 iOS实现抖音点赞动画效果 的全部内容, 来源链接: utcz.com/z/327697.html

回到顶部