Using Perspective Transform for a 3-D Flip Transition
You can easily create 3-D transitions in JavaFX by using the PerspectiveTransform effect.
Understanding the Code
All JavaFX graphics nodes have an effect variable, which you can use to apply special effects to that node. The PerspectiveTransform effect stretches the node to fit a four-sided polygon defined by four corner points. By carefully calculating these points you can create a 3-D flipping effect.
The code in Figure 1 defines a custom node called FlipView. It has two public variables for the front and back nodes and a third internal variable called time. The create function returns a Group containing two other Groups, one for the front and back nodes. The important part here is that the effect of each group is bound to the getPT function, which takes the time variable. Because it is bound, the getPT function is called every time the time variable changes. It is in the getPT function where the PerspectiveTransform is actually calculated based on the current time.
package fliptransition;
import javafx.scene.effect.*;
...
class FlipView extends CustomNode {
public var frontNode:Node;
public var backNode:Node;
var flipped = false;
var time = Math.PI/2;
override public function create():Node {
return Group {
content: [
Group { content: backNode visible: bind (time<0) effect: bind getPT(time) },
Group { content: frontNode visible: bind (time>0) effect: bind getPT(time) },
]
}
}
Figure 1: FlipView class
The getPT function uses the Math.sin() and Math.cos() methods to stretch the dimensions of the node to look like it is at a 3-D angle. On each flip, the side of the rectangle that rotates toward the back is made slightly smaller. The side of the rectangle that rotates toward the front is made slightly taller. These rotations are what creates the illusion of a 3-D transition. The width and height constants match the size of the front and back nodes. The radius and back variables can be adjusted to customize the exact angle and distortion of the effect.
function getPT(t:Number):PerspectiveTransform {
var width = 200;
var height = 200;
var radius = width/2;
var back = height/10;
return PerspectiveTransform {
ulx: radius - Math.sin(t)*radius uly: 0 - Math.cos(t)*back
urx: radius + Math.sin(t)*radius ury: 0 + Math.cos(t)*back
lrx: radius + Math.sin(t)*radius lry: height - Math.cos(t)*back
llx: radius - Math.sin(t)*radius lly: height + Math.cos(t)*back
}
}
Figure 2: getPT Function
To actually animate the transition, the anim timeline moves the time variable from negative 3.14/2 (or 90 degrees in radians) to -3.14/2 over a single second. For details see Figure 3.
public var anim = Timeline { keyFrames: [ at(0s) { time=> Math.PI/2 tween Interpolator.LINEAR}, at(1s) { time=> -Math.PI/2 tween Interpolator.LINEAR}, KeyFrame { time: 1.0s action: function() { flipped = not flipped; } } ] }Figure 3: Animate the Transition
To use the FlipView you just create it and pass in content nodes for the front and back, as Figure 4 shows.
var flip = FlipView {
translateX: 50
translateY: 40+50
backNode: ImageView { image: Image { url: "{__DIR__}lion1.png" } }
frontNode: ImageView { image: Image { url: "{__DIR__}lion2.png" } }
};
Figure 4: Create a FlipView
Josh MarinacciStaff Engineer,
Sun Microsystems