Support CSS Transitions in JavaFX.
It is not a goal to
- change the semantics of explicit transitions and animations of the
javafx.animation
framework - provide a programmatic API for implicit transitions
- support CSS Animations
CSS Transitions is a universally supported web standard that allows developers to specify how a CSS property changes its value smoothly from one value to another. Here's how an implicit transition is defined in a stylesheet:
.button {
-fx-opacity: 0.8;
transition: -fx-opacity 1s;
}
.button:hover {
-fx-opacity: 1.0;
}
CSS Transitions makes it easy to define animated transitions and create rich and fluid user experiences. CSS Transitions also nicely complements control skins: while skins define the structure and semantics of a control, implicit transitions define its dynamic appearance.
The transition
pseudo-property is added to styleable nodes, consisting of the following sub-properties:
transition-property
transition-duration
transition-delay
transition-timing-function
It is special and distinct from all other CSS properties for three reasons:
- There is no API to access this property in Java code.
- It is not returned from
Node.getClassCssMetaData
. - It is guaranteed to be applied before all other properties.
When a property value is changed by the CSS engine, we look whether a transition has been specified for the given property. If it has, the value change is animated over time. This works for all primitive property types, as well as object properties with javafx.animation.Interpolatable
values.
Note that in order for this to work reliably, we must apply the transition
pseudo-property before all other properties, as otherwise the CSS engine might not know that a transition was specified for a given property by the time the property value is changed.
It is important to note that an implicit transition is only started when the property value is changed by the CSS engine, but not when it is changed programmatically by calling Property.setValue(T)
or via a binding. This maximizes compatibility with code that assumes that programmatic value changes happen instantly.
Applications don't need to keep track of running transitions, as they are automatically cancelled when their associated control is removed from the scene graph or becomes invisible.
The new event javafx.css.TransitionEvent
signals the creation, beginning, completion and cancellation of CSS transitions. Applications can use this event to react to running transitions, for example by allowing a running transition to complete before reconfiguring the user interface or switching to a new page.
The transition-timing-function
sub-property is used to specify easing functions.
Here is a list of all easing functions available in CSS Easing Functions:
linear
ease
,ease-in
,ease-out
,ease-in-out
,cubic-bezier(x1, y1, x2, y2)
step-start
,step-end
,steps(intervals, step-position)
[wherestep-position
can be one of the following:jump-start
,jump-end
,jump-none
,jump-both
,start
,end
]
Easing functions are implemented using javafx.animation.Interpolator
in JavaFX. While it may seem straightforward to re-use existing interpolator implementations like Interpolator.EASE_IN
, Interpolator.EASE_OUT
, etc., the definitions of those interpolators don't match the definitions of CSS Easing Functions. In order to be a truthful implementation of the standard, implicit transitions use the CSS definitions, not the SMIL 3.0 definitions of the existing interpolator implementations. Additionally, the following easing functions will also be supported by JavaFX CSS:
-fx-ease-in
, which corresponds toInterpolator.EASE_IN
-fx-ease-out
, which corresponds toInterpolator.EASE_OUT
-fx-ease-both
, which corresponds toInterpolator.EASE_BOTH
The following new interpolators will be added to javafx.animation.Interpolator
:
public abstract class Interpolator {
...
/**
* Specifies the step position of a step interpolator.
* <p>
* The step position determines the location of rise points in the input progress interval, which are the
* locations on the input progress axis where the output progress value jumps from one step to the next.
*
* @since 22
*/
public enum StepPosition {
/**
* The interval starts with a rise point when the input progress value is 0.
*/
START,
/**
* The interval ends with a rise point when the input progress value is 1.
*/
END,
/**
* All rise points are within the open interval (0..1).
*/
BOTH,
/**
* The interval starts with a rise point when the input progress value is 0,
* and ends with a rise point when the input progress value is 1.
*/
NONE
}
/**
* Built-in interpolator instance that is equivalent to {@code STEPS(1, StepPosition.START)}.
*
* @since 22
*/
public static Interpolator STEP_START = STEPS(1, StepPosition.START);
/**
* Built-in interpolator instance that is equivalent to {@code STEPS(1, StepPosition.END)}.
*
* @since 22
*/
public static Interpolator STEP_END = STEPS(1, StepPosition.END);
/**
* Creates a step interpolator that divides the input time into a series of intervals, each
* interval being equal in length, where each interval maps to a constant output time value.
* The output time value is determined by the {@link StepPosition}.
*
* @param intervals the number of intervals in the step interpolator
* @param position the {@code StepPosition} of the step interpolator
* @return a new step interpolator
*
* @since 22
*/
public static Interpolator STEPS(int intervals, StepPosition position) { ... }
...
}
-
In a follow-up enhancement,
Insets
,Background
,BackgroundFill
, andCornerRadii
will implement theInterpolatable
interface to allow more types to be implicitly animated. -
CSS Animations might be implemented, which is a keyframe-based animation framework for CSS.
-
An API to programmatically define CSS transitions might be added. Not doing this right away allows the implementation to move around a bit (which it might do if we choose to also do CSS Animations).
Applications that want to offer animated user experiences can use the existing javafx.animation
framework. Animated controls can be created by subclassing existing skins and hooking into different kinds of input events and property change events to trigger animations.