本文实例为大家分享了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的计算,也算是个小重点了。

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

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

iOS实现抖音点赞动画效果的更多相关文章

  1. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  3. iOS实现拖拽View跟随手指浮动效果

    这篇文章主要为大家详细介绍了iOS实现拖拽View跟随手指浮动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  4. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  5. ios – Testflight无法安装应用程序

    我有几个测试人员注册了testflight并连接了他们的设备……他们有不同的ios型号……但是所有这些都有同样的问题.当他们从“safari”或“testflight”应用程序本身单击应用程序的安装按钮时……达到约90%并出现错误消息…

  6. ibm-mobilefirst – 在iOS 7.1上获取“无法安装应用程序,因为证书无效”错误

    当我的客户端将他们的设备更新到iOS7.1,然后尝试从AppCenter更新我们的应用程序时,我收到了上述错误.经过一番搜索,我找到了一个类似问题的帖子here.但是后来因为我在客户端使用AppCenter更新应用程序的环境中,我无法使用USB插件并为他们安装应用程序.在发布支持之前,是否有通过AppCenter进行下载的解决方法?

  7. ios – 视图的简单拖放?

    我正在学习iOS,但我找不到如何向UIView添加拖放行为.我试过了:它说“UIView没有可见的接口声明选择器addTarget”此外,我尝试添加平移手势识别器,但不确定这是否是我需要的它被称为,但不知道如何获得事件的坐标.在iOS中注册移动事件回调/拖放操作的标准简单方法是什么?

  8. ios – 什么控制iTunes中iPhone应用程序支持的语言列表?

    什么控制iPhone应用程序的iTunes页面中支持的语言?

  9. ios – 获得APNs响应BadDeviceToken或Unregistered的可能原因是什么?

    我知道设备令牌在某些时候是有效的.用户如何使其设备令牌变坏?从关于“未注册”的文档:Thedevicetokenisinactiveforthespecifiedtopic.这是否意味着应用程序已被删除?.您应该看到四种分发方法:如果您选择AppStore或Enterprise,您将在后面的对话框中看到Xcode将APNS权利更改为生产:如果选择AdHoc或Development,则aps-environment下的文本将是开发,然后应与后端的配置匹配.

  10. ios – 当我关闭应用程序时,我从调试器获得消息:由于信号15而终止

    我怎么能解决这个问题,我不知道这个链接MypreviousproblemaboutCoredata对我的问题有影响吗?当我cmd应用程序的Q时,将出现此消息.Messagefromdebugger:Terminatedduetosignal15如果谁知道我以前的问题的解决方案,请告诉我.解决方法>来自调试器的消息:每当用户通过CMD-Q(退出)或STOP手动终止应用程序(无论是在iOS模拟器中还是

随机推荐

  1. iOS实现拖拽View跟随手指浮动效果

    这篇文章主要为大家详细介绍了iOS实现拖拽View跟随手指浮动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. iOS – genstrings:无法连接到输出目录en.lproj

    使用我桌面上的项目文件夹,我启动终端输入:cd然后将我的项目文件夹拖到终端,它给了我路径.然后我将这行代码粘贴到终端中找.-name*.m|xargsgenstrings-oen.lproj我在终端中收到此错误消息:genstrings:无法连接到输出目录en.lproj它多次打印这行,然后说我的项目是一个目录的路径?没有.strings文件.对我做错了什么的想法?

  3. iOS 7 UIButtonBarItem图像没有色调

    如何确保按钮图标采用全局色调?解决方法只是想将其转换为根注释,以便为“回答”复选标记提供更好的上下文,并提供更好的格式.我能想出这个!

  4. ios – 在自定义相机层的AVFoundation中自动对焦和自动曝光

    为AVFoundation定制图层相机创建精确的自动对焦和曝光的最佳方法是什么?

  5. ios – Xcode找不到Alamofire,错误:没有这样的模块’Alamofire’

    我正在尝试按照github(https://github.com/Alamofire/Alamofire#cocoapods)指令将Alamofire包含在我的Swift项目中.我创建了一个新项目,导航到项目目录并运行此命令sudogeminstallcocoapods.然后我面临以下错误:搜索后我设法通过运行此命令安装cocoapodssudogeminstall-n/usr/local/bin

  6. ios – 在没有iPhone6s或更新的情况下测试ARKit

    我在决定下载Xcode9之前.我想玩新的框架–ARKit.我知道要用ARKit运行app我需要一个带有A9芯片或更新版本的设备.不幸的是我有一个较旧的.我的问题是已经下载了新Xcode的人.在我的情况下有可能运行ARKit应用程序吗?那个或其他任何模拟器?任何想法或我将不得不购买新设备?解决方法任何iOS11设备都可以使用ARKit,但是具有高质量AR体验的全球跟踪功能需要使用A9或更高版本处理器的设备.使用iOS11测试版更新您的设备是必要的.

  7. 将iOS应用移植到Android

    我们制作了一个具有2000个目标c类的退出大型iOS应用程序.我想知道有一个最佳实践指南将其移植到Android?此外,由于我们的应用程序大量使用UINavigation和UIView控制器,我想知道在Android上有类似的模型和实现.谢谢到目前为止,guenter解决方法老实说,我认为你正在计划的只是制作难以维护的糟糕代码.我意识到这听起来像很多工作,但从长远来看它会更容易,我只是将应用程序的概念“移植”到android并从头开始编写.

  8. ios – 在Swift中覆盖Objective C类方法

    我是Swift的初学者,我正在尝试在Swift项目中使用JSONModel.我想从JSONModel覆盖方法keyMapper,但我没有找到如何覆盖模型类中的Objective-C类方法.该方法的签名是:我怎样才能做到这一点?解决方法您可以像覆盖实例方法一样执行此操作,但使用class关键字除外:

  9. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

  10. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

返回
顶部