Trident part 2 – interpolating fields

June 22nd, 2009

Over the course of the next few days i’m going to talk about different concepts in the Trident animation library for Java applications. Part two talks about APIs to interpolate primitive and non-primitive fields of Java objects.

Interpolation of primitive fields

A timeline allows changing field values of the associated object. For example, in a fade-in animation the timeline will interpolate the value of alpha field from 0.0 to 1.0. There are two steps involved in setting up such timeline.

The first step is to create a Timeline instance passing the main object. The timeline is then configured to interpolate one or more fields of this main object. Let’s see a simple example:

import org.pushingpixels.trident.Timeline;

public class HelloWorld {
	private float value;

	public void setValue(float newValue) {
		System.out.println(this.value + " -- " + newValue);
		this.value = newValue;
	}

	public static void main(String[] args) {
		HelloWorld hello = new HelloWorld();
		Timeline timeline = new Timeline(hello);
		timeline.addPropertyToInterpolate("value", 0.0f, 1.0f);
		timeline.play();

		try {
			Thread.sleep(3000);
		} catch (Exception exc) {
		}
	}
}

Here, the timeline has the associated HelloWorld instance; this timeline is instructed to interpolate the value field of that instance from 0.0 to 1.0 over the duration of the timeline.

There is an important assumption that the application code must honor. Each field added with the addPropertyToInterpolate must have the matching public setter.

A timeline can interpolate multiple fields. In the following example the timeline will change values of three fields at each timeline pulse:

Timeline timeline = new Timeline(circle);
timeline.addPropertyToInterpolate("x", initX, finalX);
timeline.addPropertyToInterpolate("y", initY, finalY);
timeline.addPropertyToInterpolate("opacity", 1.0f, 0.0f);

Interpolating non-primitive fields

In addition to interpolating primitive fields, the Timeline.addPropertyToInterpolate APIs allow the application code to interpolate fields of other types. Each interpolation is using the matching property interpolator that implements the org.pushingpixels.trident.interpolator.PropertyInterpolator interface:

public interface PropertyInterpolator {
	public Class getBasePropertyClass();

	public T interpolate(T from, T to, float timelinePosition);
}

The interpolate method is used at each timeline pulse to compute the interpolated value. To interpolate a field using the specific property interpolator call the following Timeline API:

addPropertyToInterpolate(String, Object, Object, PropertyInterpolator)

The parameters are:

  • The field name.
  • The start value.
  • The end value.
  • The property interpolator.

Note that the application is responsible to make sure that the object passed to the timeline constructor has a public setter accepting the interpolated value returned by the interpolate implementation of this property interpolator.

The PropertyInterpolator.getBasePropertyClass is not used when the application code explicitly passes the property interpolator – and it is safe to return any value (including null) from it. This method is used only during dynamic lookup of custom property interpolators.

Additional interpolation capabilities

The addPropertyToInterpolate API above is used to interpolate a specific field from the given start value to the given end value. Application code can also use the following variations of this API:

  • addPropertyToInterpolate(Object, String, Object, Object) – to interpolate the specified field of an object different from the main timeline object. This object is passed as the first parameter to this method
  • addPropertyToInterpolate(Object, String, Object, Object, PropertyInterpolator) – to interpolate the specified field of an object different from the main timeline object using the specified property interpolator

When the start value is not known at timeline initialization time, the following APIs can be used to interpolate the field from its current value (as known at runtime) to the specified end value:

  • addPropertyToInterpolateTo(String, Object) – to interpolate the specified field of the main timeline object
  • addPropertyToInterpolateTo(Object, String, Object) – to interpolate the specified field of an object different from the main timeline object. This object is passed as the first parameter to this method
  • addPropertyToInterpolateTo(Object, String, Object, PropertyInterpolator) – to interpolate the specified field of an object different from the main timeline object using the specified property interpolator