iOS實現(xiàn)抖音點贊動畫效果
本文實例為大家分享了iOS實現(xiàn)抖音點贊動畫的具體代碼,供大家參考,具體內容如下
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。
調用的地方:
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)化的地方,還請路過的朋友多多指點。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Objective-C中利用正則去除非數(shù)字字母漢字方法實例
正則表達式對我們日常開發(fā)來說是必不可少的,下面這篇文章主要給大家介紹了關于Objective-C中如何利用正則去除非數(shù)字字母漢字的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧2018-06-06