/*
 * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javafx.animation;

import javafx.util.Duration;

import com.sun.scenario.animation.NumberTangentInterpolator;
import com.sun.scenario.animation.SplineInterpolator;

The abstract class defines several interpolate methods, which are used to calculate interpolated values. Various built-in implementations of this class are offered. Applications may choose to implement their own Interpolator to get custom interpolation behavior.

A custom Interpolator has to be defined in terms of a " curve()".

Since:JavaFX 2.0
/** * The abstract class defines several {@code interpolate} methods, which are * used to calculate interpolated values. Various built-in implementations of * this class are offered. Applications may choose to implement their own * {@code Interpolator} to get custom interpolation behavior. * <p> * A custom {@code Interpolator} has to be defined in terms of a " * {@link #curve(double) curve()}". * @since JavaFX 2.0 */
public abstract class Interpolator { private static final double EPSILON = 1e-12;
The constructor of Interpolator.
/** * The constructor of {@code Interpolator}. */
protected Interpolator() { }
Built-in interpolator that provides discrete time interpolation. The return value of interpolate() is endValue only when the input fraction is 1.0, and startValue otherwise.
/** * Built-in interpolator that provides discrete time interpolation. The * return value of {@code interpolate()} is {@code endValue} only when the * input {@code fraction} is 1.0, and {@code startValue} otherwise. */
public static final Interpolator DISCRETE = new Interpolator() { @Override protected double curve(double t) { return (Math.abs(t - 1.0) < EPSILON) ? 1.0 : 0.0; } @Override public String toString() { return "Interpolator.DISCRETE"; } };
Built-in interpolator that provides linear time interpolation. The return value of interpolate() is startValue + (endValue - startValue) * fraction.
/** * Built-in interpolator that provides linear time interpolation. The return * value of {@code interpolate()} is {@code startValue} + ({@code endValue} * - {@code startValue}) * {@code fraction}. */
public static final Interpolator LINEAR = new Interpolator() { @Override protected double curve(double t) { return t; } @Override public String toString() { return "Interpolator.LINEAR"; } }; /* * Easing is calculated with the following algorithm (taken from SMIL 3.0 * specs). The result is clamped because of possible rounding errors. * * double runRate = 1.0 / (1.0 - acceleration/2.0 - deceleration/2.0); if * (fraction < acceleration) { double averageRunRate = runRate * (fraction / * acceleration) / 2; fraction *= averageRunRate; } else if (fraction > (1.0 * - deceleration)) { // time spent in deceleration portion double tdec = * fraction - (1.0 - deceleration); // proportion of tdec to total * deceleration time double pdec = tdec / deceleration; fraction = runRate * * (1.0 - ( acceleration / 2) - deceleration + tdec * (2 - pdec) / 2); } * else { fraction = runRate * (fraction - (acceleration / 2)); } */
Built-in interpolator instance that provides ease in/out behavior.

An ease-both interpolator will make an animation start slow, then accelerate and slow down again towards the end, all in a smooth manner.

The implementation uses the algorithm for easing defined in SMIL 3.0 with an acceleration and deceleration factor of 0.2, respectively.

/** * Built-in interpolator instance that provides ease in/out behavior. * <p> * An ease-both interpolator will make an animation start slow, then * accelerate and slow down again towards the end, all in a smooth manner. * <p> * The implementation uses the algorithm for easing defined in SMIL 3.0 * with an acceleration and deceleration factor of 0.2, respectively. */
public static final Interpolator EASE_BOTH = new Interpolator() { @Override protected double curve(double t) { // See the SMIL 3.1 specification for details on this calculation // acceleration = 0.2, deceleration = 0.2 return Interpolator.clamp((t < 0.2) ? 3.125 * t * t : (t > 0.8) ? -3.125 * t * t + 6.25 * t - 2.125 : 1.25 * t - 0.125); } @Override public String toString() { return "Interpolator.EASE_BOTH"; } };
Built-in interpolator instance that provides ease in behavior.

An ease-in interpolator will make an animation start slow and then accelerate smoothly.

The implementation uses the algorithm for easing defined in SMIL 3.0 with an acceleration factor of 0.2.

/** * Built-in interpolator instance that provides ease in behavior. * <p> * An ease-in interpolator will make an animation start slow and then * accelerate smoothly. * <p> * The implementation uses the algorithm for easing defined in SMIL 3.0 * with an acceleration factor of 0.2. */
public static final Interpolator EASE_IN = new Interpolator() { private static final double S1 = 25.0 / 9.0; private static final double S3 = 10.0 / 9.0; private static final double S4 = 1.0 / 9.0; @Override protected double curve(double t) { // See the SMIL 3.1 specification for details on this calculation // acceleration = 0.2, deceleration = 0.0 return Interpolator.clamp((t < 0.2) ? S1 * t * t : S3 * t - S4); } @Override public String toString() { return "Interpolator.EASE_IN"; } };
Built-in interpolator instance that provides ease out behavior.

An ease-out interpolator will make an animation slow down toward the end smoothly.

The implementation uses the algorithm for easing defined in SMIL 3.0 with an deceleration factor of 0.2.

/** * Built-in interpolator instance that provides ease out behavior. * <p> * An ease-out interpolator will make an animation slow down toward the * end smoothly. * <p> * The implementation uses the algorithm for easing defined in SMIL 3.0 * with an deceleration factor of 0.2. */
public static final Interpolator EASE_OUT = new Interpolator() { private static final double S1 = -25.0 / 9.0; private static final double S2 = 50.0 / 9.0; private static final double S3 = -16.0 / 9.0; private static final double S4 = 10.0 / 9.0; @Override protected double curve(double t) { // See the SMIL 3.1 specification for details on this calculation // acceleration = 0.2, deceleration = 0.0 return Interpolator.clamp((t > 0.8) ? S1 * t * t + S2 * t + S3 : S4 * t); } @Override public String toString() { return "Interpolator.EASE_OUT"; } };
Creates an Interpolator, which curve() is shaped using the spline control points defined by (x1, y1 ) and (x2, y2). The anchor points of the spline are implicitly defined as (0.0, 0.0) and (1.0, 1.0).
Params:
  • x1 – x coordinate of the first control point
  • y1 – y coordinate of the first control point
  • x2 – x coordinate of the second control point
  • y2 – y coordinate of the second control point
Returns:A spline interpolator
/** * Creates an {@code Interpolator}, which {@link #curve(double) curve()} is * shaped using the spline control points defined by ({@code x1}, {@code y1} * ) and ({@code x2}, {@code y2}). The anchor points of the spline are * implicitly defined as ({@code 0.0}, {@code 0.0}) and ({@code 1.0}, * {@code 1.0}). * * @param x1 * x coordinate of the first control point * @param y1 * y coordinate of the first control point * @param x2 * x coordinate of the second control point * @param y2 * y coordinate of the second control point * @return A spline interpolator */
public static Interpolator SPLINE(double x1, double y1, double x2, double y2) { return new SplineInterpolator(x1, y1, x2, y2); }
Create a tangent interpolator. A tangent interpolator allows to define the behavior of an animation curve very precisely by defining the tangents close to a key frame. A tangent interpolator defines the behavior to the left and to the right of a key frame, therefore it is only useful within a Timeline. If used in a KeyFrame after a KeyFrame that has different interpolator, it's treated as if the out-tangent of that KeyFrame was equal to the value in the KeyFrame.

The parameters define the tangent of the animation curve for the in tangent (before a key frame) and out tangent (after a key frame). Each tangent is specified with a pair, the distance to the key frame and the value of the tangent at this moment.

The interpolation then follows a bezier curve, with 2 control points defined by the specified tangent and positioned at 1/3 of the duration before the second KeyFrame or after the first KeyFrame. See the picture above.

Params:
  • t1 – The delta time of the in-tangent, relative to the KeyFrame
  • v1 – The value of the in-tangent
  • t2 – The delta time of the out-tangent, relative to the KeyFrame
  • v2 – The value of the out-tangent
Returns:the new tangent interpolator
/** * Create a tangent interpolator. A tangent interpolator allows to define * the behavior of an animation curve very precisely by defining the * tangents close to a key frame. * * A tangent interpolator defines the behavior to the left and to the right * of a key frame, therefore it is only useful within a {@link Timeline}. * If used in a {@link KeyFrame} after a KeyFrame that has different interpolator, * it's treated as if the out-tangent of that KeyFrame was equal to the value in the KeyFrame. * * <p> * <img src="doc-files/tangent_interpolator.png" alt="A tangent interpolator * defines the behavior to the left and to the right of a key frame, * therefore it is only useful within a Timeline"> * * <p> * The parameters define the tangent of the animation curve for the in * tangent (before a key frame) and out tangent (after a key frame). Each * tangent is specified with a pair, the distance to the key frame and the * value of the tangent at this moment. * <p> * The interpolation then follows a bezier curve, with 2 control points defined by the specified tangent and * positioned at 1/3 of the duration before the second KeyFrame or after the first KeyFrame. See the picture above. * * @param t1 * The delta time of the in-tangent, relative to the KeyFrame * @param v1 * The value of the in-tangent * @param t2 * The delta time of the out-tangent, relative to the KeyFrame * @param v2 * The value of the out-tangent * @return the new tangent interpolator */
public static Interpolator TANGENT(Duration t1, double v1, Duration t2, double v2) { return new NumberTangentInterpolator(t1, v1, t2, v2); }
Creates a tangent interpolator, for which in-tangent and out-tangent are identical. This is especially useful for the first and the last key frame of a Timeline, because for these key frames only one tangent is used.
Params:
  • t – The delta time of the tangent
  • v – The value of the tangent
See Also:
Returns:the new Tangent interpolator
/** * Creates a tangent interpolator, for which in-tangent and out-tangent are * identical. This is especially useful for the first and the last key frame * of a {@link Timeline}, because for these key frames only one tangent is * used. * * @see #TANGENT(Duration, double, Duration, double) * * @param t * The delta time of the tangent * @param v * The value of the tangent * @return the new Tangent interpolator */
public static Interpolator TANGENT(Duration t, double v) { return new NumberTangentInterpolator(t, v); }
This method takes two Objects along with a fraction between 0.0 and 1.0 and returns the interpolated value.

If both Objects implement Number, their values are interpolated. If startValue implements Interpolatable the calculation defined in interpolate() is used. If neither of these conditions are met, a discrete interpolation is used, i.e. endValue is returned if and only if fraction is 1.0, otherwise startValue is returned.

Before calculating the interpolated value, the fraction is altered according to the function defined in curve().

Params:
  • startValue – start value
  • endValue – end value
  • fraction – a value between 0.0 and 1.0
Returns:interpolated value
/** * This method takes two {@code Objects} along with a {@code fraction} * between {@code 0.0} and {@code 1.0} and returns the interpolated value. * <p> * If both {@code Objects} implement {@code Number}, their values are * interpolated. If {@code startValue} implements {@link Interpolatable} the * calculation defined in {@link Interpolatable#interpolate(Object, double) * interpolate()} is used. If neither of these conditions are met, a * discrete interpolation is used, i.e. {@code endValue} is returned if and * only if {@code fraction} is {@code 1.0}, otherwise {@code startValue} is * returned. * <p> * Before calculating the interpolated value, the fraction is altered * according to the function defined in {@link #curve(double) curve()}. * * @param startValue * start value * @param endValue * end value * @param fraction * a value between 0.0 and 1.0 * @return interpolated value */
@SuppressWarnings({ "unchecked", "rawtypes" }) public Object interpolate(Object startValue, Object endValue, double fraction) { if ((startValue instanceof Number) && (endValue instanceof Number)) { final double start = ((Number) startValue).doubleValue(); final double end = ((Number) endValue).doubleValue(); final double val = start + (end - start) * curve(fraction); if ((startValue instanceof Double) || (endValue instanceof Double)) { return Double.valueOf(val); } if ((startValue instanceof Float) || (endValue instanceof Float)) { return Float.valueOf((float) val); } if ((startValue instanceof Long) || (endValue instanceof Long)) { return Long.valueOf(Math.round(val)); } return Integer.valueOf((int) Math.round(val)); } else if ((startValue instanceof Interpolatable) && (endValue instanceof Interpolatable)) { return ((Interpolatable) startValue).interpolate(endValue, curve(fraction)); } else { // discrete return (curve(fraction) == 1.0) ? endValue : startValue; } }
This method takes two boolean values along with a fraction between 0.0 and 1.0 and returns the interpolated value.

Before calculating the interpolated value, the fraction is altered according to the function defined in curve().

Params:
  • startValue – the first data point
  • endValue – the second data point
  • fraction – the fraction in [0.0...1.0]
Returns:the interpolated value
/** * This method takes two {@code boolean} values along with a * {@code fraction} between {@code 0.0} and {@code 1.0} and returns the * interpolated value. * <p> * Before calculating the interpolated value, the fraction is altered * according to the function defined in {@link #curve(double) curve()}. * * @param startValue * the first data point * @param endValue * the second data point * @param fraction * the fraction in {@code [0.0...1.0]} * @return the interpolated value */
public boolean interpolate(boolean startValue, boolean endValue, double fraction) { return (Math.abs(curve(fraction) - 1.0) < EPSILON) ? endValue : startValue; }
This method takes two double values along with a fraction between 0.0 and 1.0 and returns the interpolated value.

Before calculating the interpolated value, the fraction is altered according to the function defined in curve().

Params:
  • startValue – the first data point
  • endValue – the second data point
  • fraction – the fraction in [0.0...1.0]
Returns:the interpolated value
/** * This method takes two {@code double} values along with a {@code fraction} * between {@code 0.0} and {@code 1.0} and returns the interpolated value. * <p> * Before calculating the interpolated value, the fraction is altered * according to the function defined in {@link #curve(double) curve()}. * * @param startValue * the first data point * @param endValue * the second data point * @param fraction * the fraction in {@code [0.0...1.0]} * @return the interpolated value */
public double interpolate(double startValue, double endValue, double fraction) { return startValue + (endValue - startValue) * curve(fraction); }
This method takes two int values along with a fraction between 0.0 and 1.0 and returns the interpolated value.

Before calculating the interpolated value, the fraction is altered according to the function defined in curve().

Params:
  • startValue – the first data point
  • endValue – the second data point
  • fraction – the fraction in [0.0...1.0]
Returns:the interpolated value
/** * This method takes two {@code int} values along with a {@code fraction} * between {@code 0.0} and {@code 1.0} and returns the interpolated value. * <p> * Before calculating the interpolated value, the fraction is altered * according to the function defined in {@link #curve(double) curve()}. * * @param startValue * the first data point * @param endValue * the second data point * @param fraction * the fraction in {@code [0.0...1.0]} * @return the interpolated value */
public int interpolate(int startValue, int endValue, double fraction) { return startValue + (int) Math.round((endValue - startValue) * curve(fraction)); }
This method takes two int values along with a fraction between 0.0 and 1.0 and returns the interpolated value.

Before calculating the interpolated value, the fraction is altered according to the function defined in curve().

Params:
  • startValue – the first data point
  • endValue – the second data point
  • fraction – the fraction in [0.0...1.0]
Returns:the interpolated value
/** * This method takes two {@code int} values along with a {@code fraction} * between {@code 0.0} and {@code 1.0} and returns the interpolated value. * <p> * Before calculating the interpolated value, the fraction is altered * according to the function defined in {@link #curve(double) curve()}. * * @param startValue * the first data point * @param endValue * the second data point * @param fraction * the fraction in {@code [0.0...1.0]} * @return the interpolated value */
public long interpolate(long startValue, long endValue, double fraction) { return startValue + Math.round((endValue - startValue) * curve(fraction)); } private static double clamp(double t) { return (t < 0.0) ? 0.0 : (t > 1.0) ? 1.0 : t; }
Mapping from [0.0..1.0] to itself.
Params:
  • t – time, but normalized to the range [0.0..1.0], where 0.0 is the start of the current interval, while 1.0 is the end of the current interval. Usually a function that increases monotonically.
Returns:the curved value
/** * Mapping from [0.0..1.0] to itself. * * @param t * time, but normalized to the range [0.0..1.0], where 0.0 is the * start of the current interval, while 1.0 is the end of the * current interval. Usually a function that increases * monotonically. * @return the curved value */
protected abstract double curve(double t); }