iOS實現(xiàn)抖音點贊動畫效果
本文實例為大家分享了iOS實現(xiàn)抖音點贊動畫的具體代碼,供大家參考,具體內(nèi)容如下
1. 概述
最近看到抖音點贊愛心的動畫效果比較好,出于好奇,自己也研究仿照動畫效果寫了一個,不喜歡的朋友可不要噴我噢?。?!
話不多說,先來看一下執(zhí)行效果。

2. 動畫分析
上面的示例效果有點快,現(xiàn)在來看一個慢的,然后在分析動畫組成。

這回看清楚了吧,哈哈。
2.1 動畫過程分析
咱們就以10秒的點贊動畫來分析一下:
點贊的時候:
1、點擊的時候,白色愛心逐漸變小到一定程度,然后變成紅色愛心。(3秒)
2、紅色愛心慢慢變大,最終有個緩沖動畫,然后恢復原尺寸。(7秒)
3、在紅色愛心變大的時候,有一個紅色的圓環(huán)逐漸變大,圓環(huán)寬度由小變大,再變小消失。(5秒)
4、在紅色愛心變大的時候,還有6個環(huán)繞愛心的三角形,三角形由小變大,再變小消失。(7秒)
5、注意,2、3、4的動畫是在1動畫結束后同時執(zhí)行的,即延遲3秒再執(zhí)行。
取消點贊的時候:
1、點擊后紅色愛心逐漸變小。
2、變小后,設置不可見,并恢復原尺寸。
2.2 代碼實現(xiàn)原理分析
1、自定義一個UIView,并添加兩個UIImageView,分別顯示紅色愛心和白色愛心,紅色愛心在白色愛心上面,并設置紅色愛心不可見。
2、給UIView添加單擊手勢。
3、點擊時判斷是點贊還是取消點贊,如果是點贊:
4、用兩個UIView自帶的動畫,將白色ImageView的transform變小,變小后不可見,然后設置紅色ImageView的transform變大,變大后白色ImageView的transform變回原尺寸。
5、通過貝塞爾曲線和CAShapeLayer繪制圓環(huán),并給圓環(huán)添加動畫組CAAnimationGroup,動畫組中添加了一個基礎動畫CABasicAnimation(將圓環(huán)從小變大)和一個關鍵幀動畫CAKeyframeAnimation(將圓環(huán)寬度由小變大再變小消失)
6、通過貝塞爾曲線和CAShapeLayer循環(huán)繪制6個三角形,并通過CATransform3DMakeRotation旋轉6個三角形,使其環(huán)繞愛心一周。
7、給每個三角形添加一個關鍵幀動畫CAKeyframeAnimation(將三角形由小變大再變小消失)
8、如果是取消點贊,比較簡單,逐漸將紅色愛心變小,然后設置不可見,白色愛心自然就顯示出來了。
9、在動畫執(zhí)行過程中,關閉用戶交互,待動畫結束,再打開用戶交互。
分析的有些簡單,只是提供一種思路,沒有什么比看代碼更直接的了,來吧!
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
// 白色愛心變小后,繼續(xù)操作紅色愛心
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
}
}
//***************** 以下是圓環(huán)動畫,在紅色愛心變大的時候執(zhí)行。******************//
// 小圓環(huán)路徑
let circleStartPath = UIBezierPath(arcCenter: likeImageView.layer.position, radius: self.bounds.size.width / 6, startAngle: 0, endAngle: CGFloat(2*Double.pi), clockwise: true)
// 大圓環(huán)路徑
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)
// 創(chuàng)建圓環(huán)圖層,用于顯示圓環(huán)。
let circleLayer = CAShapeLayer()
circleLayer.strokeColor = UIColor.red.cgColor
circleLayer.fillColor = UIColor.clear.cgColor
self.layer.insertSublayer(circleLayer, below: self.likeImageView.layer)
// 計算圓環(huán)圖層的偏移時間
var currentTimeInSuper = self.layer.convertTime(CACurrentMediaTime(), from: nil)
var currentTimeLocal = circleLayer.convertTime(currentTimeInSuper, from: self.layer)
// 設置圓環(huán)動畫組執(zhí)行時間
let circleGroupDuration = duration * 0.5
// 圓環(huán)動畫組
let circleGroup = CAAnimationGroup()
circleGroup.duration = circleGroupDuration
// 圓環(huán)動畫組開始時間,此開始時間正好是白色愛心變小后,紅色愛心開始變大時。
circleGroup.beginTime = currentTimeLocal + duration * 0.3
// 設置圓環(huán)路徑變化動畫
let circlePathAnimation = CABasicAnimation(keyPath: "path")
circlePathAnimation.fromValue = circleStartPath.cgPath
circlePathAnimation.toValue = circleEndPath.cgPath
// 設置圓環(huán)寬度變化動畫,先變大,再變小。
let circleLineWidthAnimation = CAKeyframeAnimation(keyPath: "lineWidth")
circleLineWidthAnimation.values = [1.0, 4.0, 0.3]
circleLineWidthAnimation.keyTimes = [0.0, 0.7, 0.9]
// 將圓環(huán)的兩個動畫添加到動畫組。
circleGroup.animations = [circlePathAnimation, circleLineWidthAnimation]
// 將動畫添加到圓環(huán)圖層。
circleLayer.add(circleGroup, forKey: nil)
//**********************************************************************//
//***************** 以下是周圍6個三角形放射動畫,在紅色愛心變大的時候執(zhí)行。******************//
// 循環(huán)創(chuàng)建三角形圖層,并添加動畫效果
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即是自定義的點贊視圖,可純代碼創(chuàng)建,也可通過xib創(chuàng)建,同時支持設置動畫執(zhí)行時間duration。
調(diào)用的地方:
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)
}
}
執(zhí)行效果:

4. 結束語
代碼中主要用到了:UIView基礎動畫、CGAffineTransform、CATransform3D、UIBezierPath、CAShapeLayer、CAKeyframeAnimation、CABasicAnimation、CAAnimationGroup,另外還有beginTime的計算,也算是個小重點了。
以上只是仿照抖音點贊動畫實現(xiàn)的功能,代碼不多,但也不少,不知道抖音是具體怎么實現(xiàn)的,如果有什么不對的地方,或者可優(yōu)化的地方,還請路過的朋友多多指點。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Objective-C中利用正則去除非數(shù)字字母漢字方法實例
正則表達式對我們?nèi)粘i_發(fā)來說是必不可少的,下面這篇文章主要給大家介紹了關于Objective-C中如何利用正則去除非數(shù)字字母漢字的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧2018-06-06

