动画插值器-Interpolator

没有插值器的动画是没有灵魂的

Posted by Allen Vork on August 8, 2018

Synopsis

所谓的插值器就是用于控制动画的速度的。我们知道,像补间动画,只需要定义动画的第一帧和最后一帧,系统就能将中间帧都生成出来,而生成这个中间帧的过程就叫插值。默认的,动画变化是线性的,而现实生活中,动画往往是非线性的,如球从空中落下是一个重力加速度的加速过程,而刹车则是一个减速过程,为了让我们的动画更加自然,Android 提供了 Interpolator 来实现非线性动画的能力。
Interpolator 分为 TimeInterpolator 和 TypeInterpolator。

TimeInterpolator

首先我们来看下 TimeInterpolator 的源码:

/**
 * A time interpolator defines the rate of change of an animation. This allows animations
 * to have non-linear motion, such as acceleration and deceleration.
 */
public interface TimeInterpolator {

    /**
     * Maps a value representing the elapsed fraction of an animation to a value that represents
     * the interpolated fraction. This interpolated value is then multiplied by the change in
     * value of an animation to derive the animated value at the current elapsed animation time.
     *
     * @param input A value between 0 and 1.0 indicating our current point
     *        in the animation where 0 represents the start and 1.0 represents
     *        the end
     * @return The interpolation value. This value can be more than 1.0 for
     *         interpolators which overshoot their targets, or less than 0 for
     *         interpolators that undershoot their targets.
     */
    float getInterpolation(float input);
}

从解释中可以看出,getInterpolation(float input) 的参数的取值为[0, 1], 0代表动画的开始,1代表结束。即 input 代表者动画整体执行时间的进度,如一个动画执行时间为300ms,当执行到150ms时,input 的值就为0.5。这个 input 值是线性变化的,为了让动画进行非线性变化,我们就需要通过这个 input 来计算出一个新的值。下面我们来看一个例子:

public class AccelerateDecelerateInterpolator extends BaseInterpolator
        implements NativeInterpolatorFactory {

    public float getInterpolation(float input) {
        return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
    }
}

AccelerateDecelerateInterpolator 也是继承自 TimeInterpolator 的。我们通过一个绘图软件绘制一下这个公式得到的曲线图:
在[0, 1]区间,就是先加速后减速的曲线。系统为我们提供了很多插值器:

  • AccelerateDecelerateInterpolator / 先加速再减速
  • AccelerateInterpolator / 加速
  • AnticipateInterpolator / 先蓄力,回退一小步然后加速前进
  • AnticipateOvershootInterpolator / 在上一个基础上超出终点一小步再回到终点
  • BounceInterpolator / 最后阶段弹球效果
  • CycleInterpolator / 周期运动
  • DecelerateInterpolator / 减速
  • LinearInterpolator / 匀速
  • OvershootInterpolator / 快速到达终点并超出一小步最后回到终点

这些插值器的动画曲线可以查看这篇文章当然如果这些插值器不够用的话,我们可以像 AccelerateInterpolator 那样去自定义一个。

TypeEvaluator

/**
 * Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators
 * allow developers to create animations on arbitrary property types, by allowing them to supply
 * custom evaluators for types that are not automatically understood and used by the animation
 * system.
 *
 * @see ValueAnimator#setEvaluator(TypeEvaluator)
 */
public interface TypeEvaluator<T> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value.
     * @param endValue   The end value.
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public T evaluate(float fraction, T startValue, T endValue);

}

可以看出 TypeEvaluator 是通过 fraction(也就是 TimeInterpolator 中 getInterpolation() 的结果)和动画起点及终点的值来计算动画的中间值。 即 TimeInterpolator 是用来计算进度百分比,而 TypeEvaluator 是通过这个百分比来计算出当前的值。

参考文献