iOS实现抖音点赞动画效果

2025-05-29 0 41

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

1. 概述

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

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

iOS实现抖音点赞动画效果

2. 动画分析

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

iOS实现抖音点赞动画效果

这回看清楚了吧,哈哈。

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. 全部代码

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185
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。

调用的地方:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17
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)

}

}

执行效果:

iOS实现抖音点赞动画效果

4. 结束语

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 iOS实现抖音点赞动画效果 https://www.kuaiidc.com/88992.html

相关文章

发表评论
暂无评论