JavaFX 2.x
我想做什么:
PerspectiveTransform#time
- 在JavaFX 2.2中找不到)
我不想做的事情:
RotateTransition
因为它取决于PerspectiveCamera
。由于我会将许多可翻转的瓷砖彼此相邻,因此动画中途的前/后替换效果不会很好。
到目前为止我所拥有的:
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.effect.PerspectiveTransformBuilder;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* @author ggrec
*
*/
public class FX_Tester extends Application
{
@Override
public void start(final Stage stage) throws Exception
{
final StackPane stackPane = new StackPane();
final ImageView img1 = new ImageView("http://img3.wikia.nocookie.net/__cb20120816162009/mario/images/thumb/1/15/MarioNSMB2.png/200px-MarioNSMB2.png");
final ImageView img2 = new ImageView("http://img2.wikia.nocookie.net/__cb20120518002849/mario/images/thumb/7/78/Tanooki_Mario_Artwork_-_Super_Mario_Bros._3.png/180px-Tanooki_Mario_Artwork_-_Super_Mario_Bros._3.png");
final FlipView flipPane = new FlipView(img1, img2);
stackPane.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override public void handle(final MouseEvent arg0)
{
flipPane.doFlip();
}
});
stackPane.getChildren().setAll(flipPane);
stage.setScene(new Scene(stackPane));
stage.show();
}
public static void main(final String[] args)
{
launch();
}
private class FlipView extends Group
{
private Node frontNode;
private Node backNode;
private boolean isFlipped = false;
private SimpleDoubleProperty time = new SimpleDoubleProperty(Math.PI / 2);
private Timeline anim = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(time, Math.PI / 2)),
new KeyFrame(Duration.ONE, new KeyValue(time, - Math.PI / 2)),
new KeyFrame(Duration.ONE, new EventHandler<ActionEvent>() {
@Override public void handle(final ActionEvent arg0)
{
isFlipped = !isFlipped;
}
})
);
private FlipView(final Node frontNode, final Node backNode)
{
this.frontNode = frontNode;
this.backNode = backNode;
getChildren().setAll(frontNode, backNode);
frontNode.setEffect(getPT(time.doubleValue()));
backNode.setEffect(getPT(time.doubleValue()));
frontNode.visibleProperty().bind(time.greaterThan(0));
backNode.visibleProperty().bind(time.lessThan(0));
}
private PerspectiveTransform getPT(final double t)
{
final double width = 200;
final double height = 200;
final double radius = width / 2;
final double back = height / 10;
return PerspectiveTransformBuilder.create()
.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)
.build();
}
public void doFlip()
{
if (isFlipped)
{
anim.setRate(1.0);
anim.setDelay(Duration.ZERO);
}
else
{
anim.setRate(-1.0);
anim.setDelay(Duration.ONE);
}
anim.play();
}
}
}
答案 0 :(得分:7)
经过繁重的研发后,我设法实现了翻转功能,而不是 PerspectiveCamera
,只使用 PerspectiveTransform
。< / p>
如果您懒得运行 SSCCE ,那么go here to see a demo on how the below code works。
问:但乔治,这与其他方法有什么不同?
A:嗯,首先:由于您未使用PerspectiveCamera
,如果您说有100个翻转图块,则用户的观点不会受到影响屏幕。倒数第二个:后节点已被翻转。所以它没有镜像,它没有旋转,它没有缩放。它正常&#34;。 Ain那么棒?
干杯。
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* @author ggrec
*
*/
public class DFXFlipPaneTester extends Application
{
// ==================== 1. Static Fields ========================
/*
* Mmm... pie.
*/
private static final Double PIE = Math.PI;
private static final Double HALF_PIE = Math.PI / 2;
private static final double ANIMATION_DURATION = 10000;
private static final double ANIMATION_RATE = 10;
// ====================== 2. Instance Fields =============================
private Timeline animation;
private StackPane flipPane;
private SimpleDoubleProperty angle = new SimpleDoubleProperty(HALF_PIE);
private PerspectiveTransform transform = new PerspectiveTransform();
private SimpleBooleanProperty flippedProperty = new SimpleBooleanProperty(true);
// ==================== 3. Static Methods ====================
public static void main(final String[] args)
{
Application.launch(args);
}
// ==================== 5. Creators ====================
@Override
public void start(final Stage primaryStage) throws Exception
{
primaryStage.setScene(new Scene(createFlipPane()));
primaryStage.show();
}
private StackPane createFlipPane()
{
angle = createAngleProperty();
flipPane = new StackPane();
flipPane.setPadding(new Insets(30));
flipPane.setMinHeight(500);
flipPane.setMinWidth(500);
flipPane.getChildren().setAll(createBackNode(), createFrontNode());
flipPane.widthProperty().addListener(new ChangeListener<Number>() {
@Override public void changed(final ObservableValue<? extends Number> arg0, final Number arg1, final Number arg2)
{
recalculateTransformation(angle.doubleValue());
}
});
flipPane.heightProperty().addListener(new ChangeListener<Number>() {
@Override public void changed(final ObservableValue<? extends Number> arg0, final Number arg1, final Number arg2)
{
recalculateTransformation(angle.doubleValue());
}
});
return flipPane;
}
private StackPane createFrontNode()
{
final StackPane node = new StackPane();
node.setEffect(transform);
node.visibleProperty().bind(flippedProperty);
node.getChildren().setAll(createButton("Front Button")); //$NON-NLS-1$
return node;
}
private StackPane createBackNode()
{
final StackPane node = new StackPane();
node.setEffect(transform);
node.visibleProperty().bind(flippedProperty.not());
node.getChildren().setAll(createButton("Back Button")); //$NON-NLS-1$
return node;
}
private Button createButton(final String text)
{
final Button button = new Button(text);
button.setMaxHeight(Double.MAX_VALUE);
button.setMaxWidth(Double.MAX_VALUE);
button.setOnAction(new EventHandler<ActionEvent>() {
@Override public void handle(final ActionEvent arg0)
{
flip();
}
});
return button;
}
private SimpleDoubleProperty createAngleProperty()
{
// --------------------- <Angle> -----------------------
final SimpleDoubleProperty angle = new SimpleDoubleProperty(HALF_PIE);
angle.addListener(new ChangeListener<Number>() {
@Override public void changed(final ObservableValue<? extends Number> obsValue, final Number oldValue, final Number newValue)
{
recalculateTransformation(newValue.doubleValue());
}
});
return angle;
}
private Timeline createAnimation()
{
return new Timeline(
new KeyFrame(Duration.millis(0), new KeyValue(angle, HALF_PIE)),
new KeyFrame(Duration.millis(ANIMATION_DURATION / 2), new KeyValue(angle, 0, Interpolator.EASE_IN)),
new KeyFrame(Duration.millis(ANIMATION_DURATION / 2), new EventHandler<ActionEvent>() {
@Override public void handle(final ActionEvent arg0)
{
// TODO -- Do they another way or API to do this?
flippedProperty.set( flippedProperty.not().get() );
}
}),
new KeyFrame(Duration.millis(ANIMATION_DURATION / 2), new KeyValue(angle, PIE)),
new KeyFrame(Duration.millis(ANIMATION_DURATION), new KeyValue(angle, HALF_PIE, Interpolator.EASE_OUT))
);
}
// ==================== 6. Action Methods ====================
private void flip()
{
if (animation == null)
animation = createAnimation();
animation.setRate( flippedProperty.get() ? ANIMATION_RATE : -ANIMATION_RATE );
animation.play();
}
// ==================== 8. Business Methods ====================
private void recalculateTransformation(final double angle)
{
final double insetsTop = flipPane.getInsets().getTop() * 2;
final double insetsLeft = flipPane.getInsets().getLeft() * 2;
final double radius = flipPane.widthProperty().subtract(insetsLeft).divide(2).doubleValue();
final double height = flipPane.heightProperty().subtract(insetsTop).doubleValue();
final double back = height / 10;
/*
* Compute transform.
*
* Don't bother understanding these unless you're a math passionate.
*
* You may Google "Affine Transformation - Rotation"
*/
transform.setUlx(radius - Math.sin(angle) * radius);
transform.setUly(0 - Math.cos(angle) * back);
transform.setUrx(radius + Math.sin(angle) * radius);
transform.setUry(0 + Math.cos(angle) * back);
transform.setLrx(radius + Math.sin(angle) * radius);
transform.setLry(height - Math.cos(angle) * back);
transform.setLlx(radius - Math.sin(angle) * radius);
transform.setLly(height + Math.cos(angle) * back);
}
}
答案 1 :(得分:2)
Oracle创建了一个名为DisplayShelf的示例。它类似于您链接的PhotoFlip应用程序,但是是为Java 2+实现的。 Oracle示例代码位于Ensemble Sample Application中。您可以在JavaFX open source repository。
中查看DisplayShelf源代码
DisplayShelf是Cover Flow动画的PerspectiveTransform样式实现,因此它与完整图像翻转不完全相同。但是许多原则是相同的,所以你应该能够研究DisplayShelf示例,然后开发出符合你需求的代码。
JavaFX的相关图像翻转问题=&gt; Flip a card animation