swift - 头像弹性动画,类似即刻App的头像动画
2018-03-10 09:59
176 查看
首先附上 Demo地址
看下我们实现的效果
![](https://upload-images.jianshu.io/upload_images/2189604-9de5d0e813e9a0ee.gif?imageMogr2/auto-orient/strip)
效果实现应该有很多种方法,先讲一下涉及到的几个动画属性
1.UIDynamicAnimator 仿真物理属性,不懂的可以看下边的网页链接进行学习奥UIDynamicAnimator - 仿真物理学
2.UISnapBehavior 动力弹性属性,下边附带学习链接
UISnapBehavior - 动力学
3.UIAttachmentBehavior,吸附效果属性,下边是学习链接
UIAttachmentBehavior - 吸附效果
4.最后就是我们的UIPanGestureRecognizer这个我们都熟悉的手势了,
大家如果对这几个物理仿真属性不是太了解的也可以自行百度查找学习一下
为了方便外部使用,这里通过UIView的扩展(extension)实现上述效果,调用比较方便,//object代表UIView的子类,直接调用这句话即可 object.signleDragable()
我们来看下代码实现这块,因为考虑到在扩展里边没办法直接添加属性,因此。我们用到了OC里的那一套,用runtime来添加
上图![](https://upload-images.jianshu.io/upload_images/2189604-a2e2fbafc23b88a7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
上代码
private var zm_playground: UIView? { set{ objc_setAssociatedObject(self, RuntimeKey.zm_playgroundKey!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } get{ return objc_getAssociatedObject(self, RuntimeKey.zm_playgroundKey!) as? UIView } } private var zm_animator: UIDynamicAnimator? { set{ objc_setAssociatedObject(self, RuntimeKey.zm_animatorKey!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } get{ return objc_getAssociatedObject(self, RuntimeKey.zm_animatorKey!) as? UIDynamicAnimator } } private var zm_snapBehavior: UISnapBehavior? { set{ objc_setAssociatedObject(self, RuntimeKey.zm_snapBehavior!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } get{ return objc_getAssociatedObject(self, RuntimeKey.zm_snapBehavior!) as? UISnapBehavior } } private var zm_attachmentBehavior: UIAttachmentBehavior? { set{ objc_setAssociatedObject(self, RuntimeKey.zm_attachmentBehavior!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } get{ return objc_getAssociatedObject(self, RuntimeKey.zm_attachmentBehavior!) as? UIAttachmentBehavior } } private var zm_panGesture: UIPanGestureRecognizer? { set{ objc_setAssociatedObject(self, RuntimeKey.zm_panGesture!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } get{ return objc_getAssociatedObject(self, RuntimeKey.zm_panGesture!) as? UIPanGestureRecognizer } } private var zm_centerPoint: CGPoint? { set{ objc_setAssociatedObject(self, RuntimeKey.zm_centerPoint!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } get{ return objc_getAssociatedObject(self, RuntimeKey.zm_centerPoint!) as? CGPoint } } private var zm_damping: CGFloat? { set{ objc_setAssociatedObject(self, RuntimeKey.zm_damping!, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } get{ return objc_getAssociatedObject(self, RuntimeKey.zm_damping!) as? CGFloat } }
这里用这个runtime之前我还专门百度一下和OC的用法区别,果不其然。有人说key这个玩意不定义好容易为空,具体我也没细看原因。
因此,一方面为了方便,另一方面为了后期扩展,自己定义了一个结构体来承载这些key![](https://upload-images.jianshu.io/upload_images/2189604-462238cecc00d421.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
static let zm_playgroundKey = UnsafeRawPointer.init(bitPattern: "zm_playgroundKey".hashValue) static let zm_animatorKey = UnsafeRawPointer.init(bitPattern: "zm_animatorKey".hashValue) static let zm_snapBehavior = UnsafeRawPointer.init(bitPattern: "zm_snapBehaviorKey".hashValue) static let zm_attachmentBehavior = UnsafeRawPointer.init(bitPattern: "zm_attachmentBehaviorKey".hashValue) static let zm_panGesture = UnsafeRawPointer.init(bitPattern: "zm_panGestureKey".hashValue) static let zm_centerPoint = UnsafeRawPointer.init(bitPattern: "zm_centerPointKey".hashValue) static let zm_damping = UnsafeRawPointer.init(bitPattern: "zm_dampingKey".hashValue)
我们来看下核心功能区,pan手势那里都进行了什么操作
![](https://upload-images.jianshu.io/upload_images/2189604-836000b<br/>4000<br/>b108ab65f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
//swift 4.0语法,记得方法带上@objc @objc func signlePanGesture(pan: UIPanGestureRecognizer) -> Void { let panLocation = pan.location(in: zm_playground) if pan.state == .began { signleUpdateSnapPoint() let offSet = UIOffsetMake(panLocation.x - (zm_centerPoint?.x)!, panLocation.y - (zm_centerPoint?.y)!) zm_animator?.removeAllBehaviors() zm_attachmentBehavior = UIAttachmentBehavior.init(item: self, offsetFromCenter: offSet, attachedToAnchor: panLocation) zm_animator?.addBehavior(zm_attachmentBehavior!) } else if pan.state == .changed { zm_attachmentBehavior?.anchorPoint = panLocation } else if (pan.state == .ended) || (pan.state == .cancelled) || (pan.state == .failed) { zm_animator?.addBehavior(zm_snapBehavior!) zm_animator?.removeBehavior(zm_attachmentBehavior!) } }
这里分了几个步骤实现
1.当手势触发时,添加UISnapBehavior 动力弹性属性,UIAttachmentBehavior - 吸附效果,并且放到我们的UIDynamicAnimator 仿真物理属性这个里边2.当手势开始发生改变的时候,我们看动画可以看出,是一直跟着手势滑动的,因此这里把中心点坐标拿了出来
3.当我们手势结束,取消,或者出现了不可控的情况导致手势结束的情况下,移除当前动画效果就可以了
以上就是关于swift版,头像仿物理引擎动画。 Demo地址
有疑问的同学,可以下方评论区探讨奥相关文章推荐
- 【译】如何用Swift实现一个好玩的弹性动画
- Swift - 集成app启动页广告,切换rootViewController,支持LaunchImage和LaunchScreen.storyboard,支持GIF图片显示,支持视图过渡动画
- swift2.0 CASpringAnimation 和 UIView.animateWithDuration 分别实现弹性动画
- SnakeMaker:模仿实现 即刻APP 头像拖动的残影效果
- Swift-贝赛尔曲线画扇形、弧线、圆形、多边形——UIBezierPath实现App下载时的动画效果
- 如何实现百度外卖APP个人中心头像"浪"起来的动画效果
- Shine Button动画效果 类似Tinder APP的卡片界面
- 如何用Swift实现一个好玩的弹性动画
- Swift 弹性动画教程
- 如何用Swift实现一个好玩的弹性动画
- 类似 Dribbble 下载按钮的 SVG 弹性动画进度条
- 类似直播app点赞动画分析
- 用 Swift、Foursquare API 和 Realm 創建一個咖啡屋 App
- 用Swift实现一款天气预报APP(二)
- Swift开发:iOS那些简单的动画
- <Android 应用 之路> 一个类似今日头条的APP
- Swift - 使用CABasicAnimation实现动画效果
- 第二十一篇玩转【斗鱼直播APP】系列之加载数据动画
- Swift--图片旋转动画
- 使用 electron 实现类似新版 QQ 的登录界面效果(阴影、背景动画、窗体3D翻转)