javafx 可套用 transformation 在單一或一組 nodes,也可以針對某一個 node,同時套用多個 transformations。
transformation
transformation 有以下這幾種
- Rotation:旋轉
- Scaling:縮放
- Translation:平移
- Shearing(斜切):用仿射變換實現
package javafx.transformation;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.*;
import javafx.stage.Stage;
//Rotation:旋轉
//Scaling:縮放
//Translation:平移
//Shearing(斜切):用仿射變換實現
public class TransformDemo extends Application {
@Override
public void start(Stage primaryStage) {
// === 建立形狀 ===
Rectangle rect = new Rectangle(100, 60, Color.CORNFLOWERBLUE);
rect.setArcWidth(15);
rect.setArcHeight(15);
// === 各種變換按鈕 ===
Button btnTranslate = new Button("Translate (+100, +50)");
btnTranslate.setOnAction(e -> {
rect.getTransforms().add(new Translate(100, 50));
});
Button btnRotate = new Button("Rotate 45°");
btnRotate.setOnAction(e -> {
rect.getTransforms().add(new Rotate(45, rect.getX() + rect.getWidth() / 2, rect.getY() + rect.getHeight() / 2));
});
Button btnScale = new Button("Scale x1.5");
btnScale.setOnAction(e -> {
rect.getTransforms().add(new Scale(1.5, 1.5, rect.getX() + rect.getWidth() / 2, rect.getY() + rect.getHeight() / 2));
});
Button btnShear = new Button("Shear x=0.5, y=0");
btnShear.setOnAction(e -> {
rect.getTransforms().add(new Shear(0.5, 0));
});
// === Reset 按鈕 ===
Button btnReset = new Button("Reset Transforms");
btnReset.setStyle("-fx-background-color: tomato; -fx-text-fill: white;");
btnReset.setOnAction(e -> {
rect.getTransforms().clear(); // 移除所有變換
});
// === 佈局 ===
VBox root = new VBox(15,
rect,
btnTranslate,
btnRotate,
btnScale,
btnShear,
btnReset
);
root.setPadding(new Insets(20));
Scene scene = new Scene(root, 500, 400);
primaryStage.setTitle("JavaFX Transformations with Reset");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
transition
transform 是一種即時的直接的轉換,會直接改變 node 的屬性,立刻生效。用作 node 的幾何變換。
transition 是一種動畫,需要一段時間,才會轉換到結果的動畫,可以 delay, repeat,有移動、縮放、旋轉、淡入淡出、路徑移動、視覺強化這些動態轉換的效果。
package javafx.transition;
import javafx.animation.*;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import javafx.util.Duration;
public class AllTransitionsDemo extends Application {
private Rectangle rect;
// 紀錄狀態
private double currentTranslateX = 0;
private double currentTranslateY = 0;
private double currentRotate = 0;
private double currentScaleX = 1;
private double currentScaleY = 1;
@Override
public void start(Stage primaryStage) {
rect = new Rectangle(100, 60, Color.CORNFLOWERBLUE);
rect.setArcWidth(15);
rect.setArcHeight(15);
rect.setStroke(Color.DARKBLUE);
rect.setStrokeWidth(3);
// RotateTransition
Button btnRotate = new Button("Rotate +45°");
btnRotate.setOnAction(e -> {
currentRotate += 45;
RotateTransition rt = new RotateTransition(Duration.seconds(1), rect);
rt.setToAngle(currentRotate);
rt.play();
});
// ScaleTransition
Button btnScale = new Button("Scale x1.5");
btnScale.setOnAction(e -> {
currentScaleX *= 1.5;
currentScaleY *= 1.5;
ScaleTransition st = new ScaleTransition(Duration.seconds(1), rect);
st.setToX(currentScaleX);
st.setToY(currentScaleY);
st.play();
});
// TranslateTransition
Button btnTranslate = new Button("Translate (+100, +50)");
btnTranslate.setOnAction(e -> {
currentTranslateX += 100;
currentTranslateY += 50;
TranslateTransition tt = new TranslateTransition(Duration.seconds(1), rect);
tt.setToX(currentTranslateX);
tt.setToY(currentTranslateY);
tt.play();
});
// FadeTransition
Button btnFade = new Button("Fade Out / In");
btnFade.setOnAction(e -> {
FadeTransition ft = new FadeTransition(Duration.seconds(1), rect);
ft.setFromValue(1.0);
ft.setToValue(0.2);
ft.setAutoReverse(true);
ft.setCycleCount(2);
ft.play();
});
// FillTransition (填充色)
Button btnFill = new Button("Fill Color Change");
btnFill.setOnAction(e -> {
FillTransition fillTransition = new FillTransition(Duration.seconds(2), rect);
fillTransition.setFromValue((Color) rect.getFill());
fillTransition.setToValue(Color.ORANGERED);
fillTransition.setAutoReverse(true);
fillTransition.setCycleCount(2);
fillTransition.play();
});
// StrokeTransition (邊框色)
Button btnStroke = new Button("Stroke Color Change");
btnStroke.setOnAction(e -> {
StrokeTransition strokeTransition = new StrokeTransition(Duration.seconds(2), rect);
strokeTransition.setFromValue((Color) rect.getStroke());
strokeTransition.setToValue(Color.GREEN);
strokeTransition.setAutoReverse(true);
strokeTransition.setCycleCount(2);
strokeTransition.play();
});
// SequentialTransition
Button btnSequential = new Button("Sequential Animation");
btnSequential.setOnAction(e -> {
RotateTransition rotate = new RotateTransition(Duration.seconds(1), rect);
rotate.setByAngle(90);
TranslateTransition translate = new TranslateTransition(Duration.seconds(1), rect);
translate.setByX(100);
translate.setByY(50);
ScaleTransition scale = new ScaleTransition(Duration.seconds(1), rect);
scale.setToX(1);
scale.setToY(1);
SequentialTransition seq = new SequentialTransition(rect, rotate, translate, scale);
seq.play();
});
// ParallelTransition
Button btnParallel = new Button("Parallel Animation");
btnParallel.setOnAction(e -> {
RotateTransition rotate = new RotateTransition(Duration.seconds(2), rect);
rotate.setByAngle(180);
FadeTransition fade = new FadeTransition(Duration.seconds(2), rect);
fade.setFromValue(1);
fade.setToValue(0.3);
ParallelTransition parallel = new ParallelTransition(rect, rotate, fade);
parallel.play();
});
// PauseTransition
Button btnPause = new Button("Pause 2 Seconds");
btnPause.setOnAction(e -> {
PauseTransition pause = new PauseTransition(Duration.seconds(2));
pause.setOnFinished(ev -> System.out.println("Pause finished"));
pause.play();
});
// PathTransition
Button btnPath = new Button("Path Animation");
btnPath.setOnAction(e -> {
Path path = new Path();
path.getElements().add(new MoveTo(0, 0));
path.getElements().add(new CubicCurveTo(150, 100, 300, 0, 400, 100));
PathTransition pathTransition = new PathTransition(Duration.seconds(3), path, rect);
pathTransition.setCycleCount(1);
pathTransition.play();
});
// Reset 按鈕
Button btnReset = new Button("Reset All");
btnReset.setStyle("-fx-background-color: tomato; -fx-text-fill: white;");
btnReset.setOnAction(e -> {
rect.getTransforms().clear();
rect.setTranslateX(0);
rect.setTranslateY(0);
rect.setRotate(0);
rect.setScaleX(1);
rect.setScaleY(1);
rect.setOpacity(1);
rect.setFill(Color.CORNFLOWERBLUE);
rect.setStroke(Color.DARKBLUE);
currentTranslateX = 0;
currentTranslateY = 0;
currentRotate = 0;
currentScaleX = 1;
currentScaleY = 1;
});
VBox root = new VBox(10,
rect,
btnRotate,
btnScale,
btnTranslate,
btnFade,
btnFill,
btnStroke,
btnSequential,
btnParallel,
btnPause,
btnPath,
btnReset
);
root.setPadding(new Insets(15));
Scene scene = new Scene(root, 600, 700);
primaryStage.setTitle("JavaFX All Transitions Demo");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
沒有留言:
張貼留言