基础动画规格 AnimationSpec
compose动画最基本的元素AnimationSpec,是compose动画的灵魂,定义了动画如何运动(物理曲线,持续时间,缓动效果等)。
分类
我个人分为两大类:基础动画和循环动画,基础动画包括物理模型的弹簧动画 和时间段的补间动画 ,关键帧动画 ,跳转动画 ;循环动画包含有限和无限 的,都是对时间动画的封装。 具体关系可以看AnimationSpec的继承关系图。
物理模型动画
SpringSpec 弹簧
定义:
使用提供的工厂函数spring
构建
kotlin
@Stable
public fun <T> spring(
dampingRatio: Float = Spring.DampingRatioNoBouncy,
stiffness: Float = Spring.StiffnessMedium,
visibilityThreshold: T? = null
): SpringSpec<T> = SpringSpec(dampingRatio, stiffness, visibilityThreshold)
参数:
- dampingRatio : Float
阻尼强度,越大越弹不动,1f无弹跳动画,0f无限次弹跳。 - stiffness : Float
弹性刚度,值越大,弹得越快。 - visibilityThreshold: T? 动画提前结束的阈值,比如动画状态类型是Float,那么可以设置当目标达到0.1f时就认为动画可以结束了,默认是null。
持续时间动画
TweenSpec 补间动画
定义:
使用提供的工厂函数tween
构建
kotlin
@Stable
public fun <T> tween(
durationMillis: Int = DefaultDurationMillis,
delayMillis: Int = 0,
easing: Easing = FastOutSlowInEasing
): TweenSpec<T> = TweenSpec(durationMillis, delayMillis, easing)
参数:
- durationMillis: Int
动画持续时间 - delayMillis: Int
动画延迟多久开始执行 - easing: Easing
缓动曲线,一般使用时间维度的贝塞尔曲线CubicBezierEasing
。
可以在这个网站上看下贝塞尔曲线:贝塞尔曲线在线编辑
KeyframesSpec 关键帧动画
精确控制每一个时间点的动画,相比较tween,可以更精细的控制。
定义:
kotlin
@Stable
public fun <T> keyframes(init: KeyframesSpecConfig<T>.() -> Unit): KeyframesSpec<T> {
return KeyframesSpec(KeyframesSpecConfig<T>().apply(init))
}
参数是一个配置类,看起来比较麻烦,但是compose提供了三个中缀函数at
,atFraction
,using
来传递参数,先看参数解释,再看下面的使用方式:
参数:
- durationMillis: Int 动画持续时间
- delayMillis: Int 动画延迟多久开始执行
<targetValue> at <time> using <Easing>
目标值 在时间点 使用缓动曲线
使用:
- 一维动画(类型就是Int,Float这种线性的变化)
kotlin
keyframes<Int> {
durationMillis = 3000
delayMillis = 1000
0 at 0 using LinearEasing //注意:缓动函数应用的是此帧到下一帧,而不是上一帧到此帧。
100 atFraction 0.3f //除了使用具体时间,还可以使用atFraction指定总时间的百分比
200 at 2000
... ...
}
- 二维动画(类型是Offset这种位置的变化,x和y轴都会变)
kotlin
keyframes<IntOffset> {
durationMillis = 1000
//Offset这种二维属性除了使用线性的时间缓动,还可以使用路径缓动ArcBelow设置移动的路径。
IntOffset(0, 0) at 0 using LinearEasing using ArcBelow
IntOffset(0, 100) at 1000
}
Ps: ArcBelow只是简单的路径缓动(基于椭圆形),想要精细的控制移动的路径,需要使用PathEasing。
KeyframesWithSplineSpec 平滑的关键帧动画
相比较普通的关键帧动画,它使用了Monotone cubic Hermite spline
这种插值算法来对帧节点之间的过渡做平滑处理,普通的关键帧动画使用的是线性插值,意味着在帧节点可能因为设置的变化过大出现突变,但是keyframesWithSplineSpec会自动对帧节点的过渡平滑处理,一定不会出现突变。
periodicBias参数
KeyframesWithSplineSpec有一个重载函数,多了一个periodicBias参数, 这个参数的作用是循环动画中为了实现首尾速度一致(周期性速度连续性),优先修改起始切线速度还是结束切线速度的权重。
compose的注解是一句话:A value from 0f to 1f, indicating how much the starting or ending velocities are modified respectively to achieve periodicity.
详细理解:
-
速度(Velocity): 在动画中,"速度"可以理解为动画值变化的快慢,对应到样条曲线上就是切线的斜率。斜率越大,变化越快。
-
周期性(Periodicity): 指的是动画从头到尾播放完后,能够平滑地衔接回开头,形成一个无缝的循环。为了实现这一点,动画结束时的"出速度"应该和开始时的"入速度"相等。
-
偏向(Bias): periodicBias 就是一个"偏向"或"权重"值。它决定了在多大程度上为了"周期性"而去修改首尾的速度。
那么0f就是完全不考虑周期性,1f就是完全考虑周期性,会让首尾的动画连贯起来。
定义:
kotlin
public fun <T> keyframesWithSpline(
init: KeyframesWithSplineSpec.KeyframesWithSplineSpecConfig<T>.() -> Unit
): KeyframesWithSplineSpec<T> =
KeyframesWithSplineSpec(
config = KeyframesWithSplineSpec.KeyframesWithSplineSpecConfig<T>().apply(init)
)
public fun <T> keyframesWithSpline(
@FloatRange(0.0, 1.0) periodicBias: Float,
init: KeyframesWithSplineSpec.KeyframesWithSplineSpecConfig<T>.() -> Unit
): KeyframesWithSplineSpec<T> =
KeyframesWithSplineSpec(
config = KeyframesWithSplineSpec.KeyframesWithSplineSpecConfig<T>().apply(init),
periodicBias = periodicBias,
)
使用:
跟前面的KeyframesSpec 一样的使用方式,用到中缀函数传递参数。
kotlin
keyframesWithSpline(periodicBias = 0.5f) {
durationMillis = 2000
1f at 1000 using LinearEasing
},
SnapSpec 跳转动画
这个很简单,无中间过程,立刻跳转到目标值。
定义:
kotlin
@Stable public fun <T> snap(delayMillis: Int = 0): SnapSpec<T> = SnapSpec<T>(delayMillis)
ArcAnimationSpec 路径动画
这还是一个试验性质的动画(当前使用的动画版本是1.8.2),主要用于二维移动的路径控制,走一个漂亮弧形。还没有工厂函数提供出来,其中路径模式就是前面关键帧动画使用的ArcMode,其他都是见过的,没啥可讲的,后续版本可能有更多的功能设计。
定义:
kotlin
@ExperimentalAnimationSpecApi
@Immutable
public class ArcAnimationSpec<T>(
public val mode: ArcMode = ArcBelow,
public val durationMillis: Int = DefaultDurationMillis,
public val delayMillis: Int = 0,
public val easing: Easing = FastOutSlowInEasing // Same default as tween()
) : DurationBasedAnimationSpec<T>
重复动画
重复动画已经不是最基础的动画了,是对时间动画的封装使用。
RepeatableSpec 有限动画
定义:
kotlin
@Stable
public fun <T> repeatable(
iterations: Int,
animation: DurationBasedAnimationSpec<T>,
repeatMode: RepeatMode = RepeatMode.Restart,
initialStartOffset: StartOffset = StartOffset(0)
): RepeatableSpec<T> = RepeatableSpec(iterations, animation, repeatMode, initialStartOffset)
参数:
- iterations: Int
重复次数 - animation: DurationBasedAnimationSpec
时间基础动画 - repeatMode: RepeatMode
重复模式(Restart/Reverse) - initialStartOffset: StartOffset
开始动画偏移量,传入偏移时间和偏移类型,类型包括Delay/FastForward
偏移类型的Delay就是等待一段时间后才开始下一轮动画,FastForward意思是下一轮的动画直接从传入的时间点开始,也就是提前执行。
InfiniteRepeatableSpec 无限动画
定义:
和有限动画的区别就是少了重复次数,其他一样的。
kotlin
@Stable
public fun <T> infiniteRepeatable(
animation: DurationBasedAnimationSpec<T>,
repeatMode: RepeatMode = RepeatMode.Restart,
initialStartOffset: StartOffset = StartOffset(0)
): InfiniteRepeatableSpec<T> = InfiniteRepeatableSpec(animation, repeatMode, initialStartOffset)
这篇文章学习了compose的所有基础动画,但是没有应用,下篇开始最基本的应用,就可以用代码展现动画效果了,喜欢我的文章请点赞收藏:)