Physics-based Animations依赖注意以及运动方程式
Physics-based Animations
基本介绍以及使用可见官方文档(见下面的链接),本文说一下使用的注意点以及两种动画对应的运动方程式
==添加依赖
dependencies {
...
compile "com.android.support:support-dynamic-animation:26.0.0-beta2"
}
注意,如果gradle出现解析错误,则需要在工程的build.gradle中加入
allprojects {
repositories {
...
maven { url 'https://maven.google.com' }
}
}
FlingAnimation
==运动方程
由牛顿第二定律得到
得到
FlingAnimation.class中有个默认的DragForce.class,设置friction时会乘以默认的参数
mFriction = frictionScalar * DEFAULT_FRICTION(4.2);
即我们设置的friction其实是frictionScale
==示例(kotlin)
val iconCircle = findViewById<ImageView>(R.id.icon_circle)
val flingAnim = FlingAnimation(iconCircle, DynamicAnimation.TRANSLATION_Y)
flingAnim.addUpdateListener { animation, value, velocity ->
Log.d("fling", value.toString() + "/" + velocity + "/" + (velocity + 4.2f * value - 1000f)) // DEFAULT_FRICTION = 4.2f
}
flingAnim.setStartVelocity(1000f)
.setMinValue(0f)
.setMaxValue(1000f)
.setFriction(1f)
.start()
位移速度以及(velocity + 4.2f * value - 1000f):
D/fling: 0.0/1000.0/0.0
D/fling: 23.732254/900.3245/0.0
D/fling: 35.122684/852.48474/0.0
---
D/fling: 166.1669/302.09915/1.2207031E-4
D/fling: 171.12354/281.2813/1.2207031E-4
---
D/fling: 225.82143/51.55015/1.2207031E-4
D/fling: 226.66722/47.9978/6.1035156E-5
D/fling: 227.45474/0.0/-44.690125
(velocity + 4.2f * value - 1000f) 皆为零,最后一个为-44.7,是因为考虑了mVelocityThreshold, 默认值为46.875,小于这个值的速度直接处理为零,所以终点一般不满足方程式。
DragForce.class中
MassState updateValueAndVelocity(float value, float velocity, long deltaT) {
mMassState.mVelocity = (float) (velocity * Math.exp((deltaT / 1000f) * mFriction));
mMassState.mValue = (float) (value - velocity / mFriction
+ velocity / mFriction * Math.exp(mFriction * deltaT / 1000f));
if (isAtEquilibrium(mMassState.mValue, mMassState.mVelocity)) {
mMassState.mVelocity = 0f;
}
return mMassState;
}
public boolean isAtEquilibrium(float value, float velocity) {
return Math.abs(velocity) < mVelocityThreshold;
}
SpringAnimation
==阻尼振动方程的解
其中
ωn为固有频率,ξ为阻尼比
SpringForce.class中 dampingRatio为ξ, stiffness为ωn^2(忽略质量, k=ωn^2)
SpringForce里计算位移和速度的公式就是上面的三个解。可以查看里面的方法
DynamicAnimation.MassState updateValues(double lastDisplacement, double lastVelocity,long timeElapsed) {--}
== 验证阻尼比ξ = 1的情况
代码(kotlin):
val springAnim = SpringAnimation(iconAndroid, DynamicAnimation.TRANSLATION_Y)
springAnim.setStartValue(0f)
springAnim.setStartVelocity(2000f)
springAnim.spring = SpringForce(0f)
springAnim.spring.dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY // 阻尼比ξ = c / 2 *sqrt(k*m) springAnim.spring.stiffness = 100f // 弹性系数 k
springAnim.addUpdateListener { animation, value, velocity ->
Log.d("update", value.toString() + "-" + velocity)
}
springAnim.start()
位移和速度的数值:
D/update: 0.0-2000.0
D/update: 40.09468-1141.1564
D/update: 51.973465-847.98816
D/update: 60.653065-606.5307
D/update: 73.00179-99.54792
D/update: 73.572235--7.2843637
D/update: 72.517784--110.62034
D/update: 70.174644--178.05505
D/update: 66.48842--227.46037
----
D/update: 12.500641--95.31368
D/update: 11.057183--85.269356
---
D/update: 1.0386676--8.952051
D/update: 0.8968631--7.758289
D/update: 0.77401096--6.7189865
D/update: 0.0-0.0
位移和速度的关系:
根据临界阻尼解的方程并代入初始值t = 0, x = 0, v = v0可以得到
求导可以得到速度公式,
消除时间t可得速度和位移之间的关系
将上面得到的数值代入此公式,皆成立。
欠阻尼和过阻尼的情况应该也是成立的,就不再做验证了(验证的话,也有点麻烦)。
参考:
https://developer.android.com/topic/libraries/support-library/preview/physics-based-animation.html 官方文档。语言最好设置为英文,中文文档可能没有即使更新