GPUAnimation 0.1.0

GPUAnimation 0.1.0

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布最后发布2016年11月
SPM支持 SPM

Luke Zhao 维护。



  • Luke

GPUAnimation

需要 Swift 3,iOS 9

使用 Metal 进行高效处理的 iOS UIKit 动画库。
它提供了一个优雅的 Swift API,用于动画您喜欢的任何属性。
保存 CPU 时间,用于处理事件而不是计算动画步骤。

注意:此版本目前为 BETA,请谨慎使用。

目录

安装

用法

view.animate {
  $0.alpha.target = 0.5
  $0.center.target = CGPoint(x:100,y:200)
}.delay(2.0).animate {
  $0.center.target = CGPoint(x:50,y:50)
  $0.center.onChange = { newCenter in
    print(newCenter)
  }
  $0.backgroundColor.target = UIColor.black
}.then {
  print("Animation completed")
}

动画属性

弹簧动画

弹簧动画最适合用于交互元素。无法指定动画的持续时间。相反,您指定弹簧的刚度阻尼。这就像在动画对象和目标之间连接一个弹簧。对象将遵循类似于平滑速度曲线的物理学。即使您更改动画目标,对象也会保持其速度,并按照自然曲线追踪新的目标。

您可以调整以下值来调整弹簧属性

  • 刚度(弹簧上的张力,值越大 -> 动画速度越快,默认:200)
  • 阻尼(弹簧上的摩擦,值越大 -> 弹跳性越小,默认:10)
  • 阈值(结束阈值,如果速度和距离都低于此阈值,则动画结束,默认:0.01)

调整这些值的方法如下

view.animate {
  # this tells the animator to use spring animation with stiffness of 200, damping of 25, and default threshold
  $0.type = .Spring(stiffness: 200, damping: 25, threshold: nil)

  $0.center.target = CGPoint(x:100,y:200) // this animation is affected by the spring animation
  $0.bounds.target = CGRect(x:0,y:0,width:100,height:100) // this is also affected
}.animate{
  $0.backgroundColor.target = UIColor.black // this is not affected(still uses default stiffness, etc..)
}

请注意,默认动画类型是 .Spring(stiffness: 200, damping: 10, threshold: 0.001)

缓动动画

这是基本动画,允许您指定持续时间和曲线。当时间持续到时间达到时,对象将位于目标位置。

view.animate {
  # this tells the animator to use tween animation with a bounce curve
  $0.type = .Tween(duration: 2.0, curve: .bounce)

  $0.center.target = CGPoint(x:100,y:200) // this animation is affected by the tween animation
  $0.bounds.target = CGRect(x:0,y:0,width:100,height:100) // this is also affected
}.animate{
  $0.backgroundColor.target = UIColor.black // this is not affected (still uses spring animation)
}

并发执行

默认情况下,所有属性(例如,以下示例中的 alphacenterbackgroundColor)都同时动画化。

view.animate {
  $0.alpha.target = 0.5
  $0.center.target = CGPoint(x:100,y:200)
}.animate {
  $0.backgroundColor.target = UIColor.black
}

顺序执行

使用 .then.delay(time) 将动画分离成顺序组。

例如以下示例中,首先动画化 alphacenter。然后是 backgroundColor。然后2.0秒后,动画化 bounds

view.animate {
  $0.alpha.target = 0.5
  $0.center.target = CGPoint(x:100,y:200)
}.then.animate {
  $0.backgroundColor.target = UIColor.black
}.delay(2.0).animate {
  $0.bounds.target = CGRect(x:0,y:0,width:100,height:100)
}

高级控件

延迟动画

view.delay(2).animate {
  // this animation is trigger after 2 seconds
  $0.alpha.target = 0.5
}.delay(2).animate {
  // this animation is trigger after 4 seconds
  $0.backgroundColor.target = UIColor.black
}

注册回调

使用 .then{ } 为动画完成注册回调

view.animate {
  $0.alpha.target = 0.5
  $0.center.target = CGPoint(x:100,y:200)
}.then {
  print("First batch done!")
}.animate {
  $0.backgroundColor.target = UIColor.black
}.then {
  print("Second batch done!")
}

观察值或速度变化

view.animate{
  $0.center.target = CGPoint(x:200, y:200)
  $0.center.onChange = { newCenter in
    print(newCenter)
  }
  $0.center.onVelocityChange = { velocity in
    print("velocity:\(velocity)")
  }
}

UIView 可动画属性

  • frame
  • bounds
  • center
  • backgroundColor
  • alpha
  • shadowColor
  • shadowRadius
  • shadowOffset
  • shadowOpacity
  • transform
    • scale
    • rotate
    • translate

动画自定义属性

对于 UIView

view.animate{
  $0.custom(key: "myCustomProperty",
            getter: { return view.myCustomProperty.toVec4 },
            setter: { nv in view.myCustomProperty = CGFloat.fromVec4(nv) },
            target: 100.toVec4 )
}

对于任何其他对象。您可以使用 GPUAnimator 提供的底层 API

class GPUAnimator{
  // spring animation
  func animate(_ item:T,
               key:String,
               getter:@escaping () -> float4,
               setter:@escaping (inout float4) -> Void,
               target:float4,
               stiffness:Float = 200,
               damping:Float = 10,
               threshold:Float = 0.01,
               completion:((Bool) -> Void)? = nil)

  // tween animation
  func animate(_ item:T,
               key:String,
               getter:@escaping () -> float4,
               setter:@escaping (float4) -> Void,
               target:float4,
               duration:Float,
               curve:Curve = .ease,
               completion:((Bool) -> Void)? = nil)

  // getting the velocity for a current running animation
  func velocityFor(_ item:T, key:String)
}

// Example
class Foo{
  var a:CGFloat = 0
}
var f = Foo()
// Animate f.a to 5, and print out it's velocity whenever the value changes
GPUAnimator.sharedInstance.animate(f, 
                                   key:"a", 
                                   getter:{ return f.a.toVec4 }, 
                                   setter:{ 
                                     f.a = CGFloat.fromVec4($0)
                                     print(GPUAnimator.sharedInstance.velocityFor(f, key:"a"))
                                   },
                                   target:5.0.toVec4)