Build Status Swift 5.0 GitHub release SwiftPM compatible CocoaPods compatible

Advance

一个适用于 iOS、tvOS 和 macOS 的动画库,它使用基于物理的动画(包括弹簧动画)来驱动交互,使其移动和响应更加真实自然。

let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

// Springs animate changes to a value
let spring = Spring(initialValue: view.center)

// The `onChange` closure will be called every time the spring updates
spring.onChange = { [view] newCenter in
    view.center = newCenter
}

/// The view's center will realistically animate to the new target value.
spring.target = CGPoint(x: 300, y: 200)

安装

有几种方法可以将 Advance 集成到你的项目中。

要求

用法

API 文档在此处提供。

Advance 动画在每一帧上应用(在 iOS/tvOS 上使用 CADisplayLink,在 macOS 上使用 CVDisplayLink),从而可以在任何时候进行精细的控制。

Spring

Spring 实例使用弹簧物理原理,随时间推移动画值的变化。

let spring = Spring(initialValue: 0.0)
spring.onChange = { [view] newAlpha in 
    view.alpha = newAlpha 
}

// Off it goes!
spring.target = 0.5

配置弹簧

/// Spring values can be adjusted at any time.
spring.tension = 30.0 /// The strength of the spring
spring.damping = 2.0 /// The resistance (drag) that the spring encounters
spring.threshold = 0.1 /// The maximum delta between the current value and the spring's target (for each component) for which the simulation can enter a converged state.

/// Update the simulation state at any time.
spring.velocity = 6.5
spring.value = 0.2

/// Sets the spring's target and the current simulation value, and removes all velocity. This causes the spring to converge at the given value.
spring.reset(to: 0.5)

Animator

Animator 允许在可以执行的动画类型方面有更大的灵活性,但为此牺牲了一些便利性。具体来说,animator 允许为单个值执行任何类型的动画或模拟。

let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

/// Animators coordinate animations to drive changes to a value.
let sizeAnimator = Animator(initialValue: view.bounds.size)

sizeAnimator.onChange = { [view] newSize in
    view.bounds.size = newSize
}

/// A simple timed animation
sizeAnimator.animate(to: CGSize(width: 123, height: 456), duration: 0.25, timingFunction: .easeInOut)

/// Some time in the future (before the previous timed animation was complete)...

/// Spring physics will move the view's size to the new value, maintaining the velocity from the timed animation.
sizeAnimator.simulate(using: SpringFunction(target: CGSize(width: 300, height: 300)))

/// Some time in the future (before the previous spring animation was complete)...

/// The value will keep the same velocity that it had from the preceeding spring
/// animation, and a decay function will slowly bring movement to a stop.
sizeAnimator.simulate(using: DecayFunction(drag: 2.0))

Animator 支持两种根本不同的动画类型:定时动画和模拟动画。

定时动画

定时动画,顾名思义,是定时的:它们有一个固定的持续时间,并以可预测的方式动画到最终值。

animator.animate(to: CGSize(width: 123, height: 456), duration: 0.25, timingFunction: .easeInOut)

TimingFunction 描述了定时动画的节奏。

TimingFunction 附带一组标准函数。

TimingFunction.linear // No easing
TimingFunction.easeIn
TimingFunction.easeOut
TimingFunction.easeInOut
TimingFunction.swiftOut // Similar to Material Design's default curve

自定义 timing 函数可以表示为单位贝塞尔曲线(此处描述)。

let customTimingFunction = TimingFunction(x1: 0.1, y1: 0.2, x2: 0.6, y2: 0.0)

模拟动画

模拟动画使用模拟函数来驱动基于物理的过渡效果。模拟函数是符合 SimulationFunction 协议的类型。

模拟动画可以使用两种不同的方法启动。

// Begins animating with the custom simulation function, maintaining the previous velocity of the animator.
animator.simulate(using: MyCustomFunction())

// or...

// Begins animating with the custom simulation function, imparting the specified velocity into the simulation.
animator.simulate(using: DecayFunction(), initialVelocity: dragGestureRecognizer.velocity(in: view))

动画自定义类型

符合 VectorConvertible 协议的值可以通过 Advance 进行动画处理。符合的类型可以转换为 Vector 实现,也可以从 Vector 实现转换而来。

public protocol VectorConvertible: Equatable, Interpolatable {
    associatedtype VectorType: SIMD where VectorType.Scalar == Double
    init(vector: VectorType)
    var vector: VectorType { get }
}

该库通过扩展为许多常见类型添加了符合性。

贡献

如果你遇到任何问题或意外情况,请提交 issue。

对于建议或新功能,请考虑提交包含功能实现的 PR。如果你不确定如何实现更改,可以使用 issue,但通常情况下,可运行的代码更容易评估。

许可证

本项目根据 BSD 2-clause 许可证发布。