在javafx中旋转X轴上的滚动窗格 - 星球大战就像效果一样

时间:2017-01-16 22:08:46

标签: java javafx user-controls transform

我在javafx中旋转用户控件时遇到问题。我的设置如下:

我在中心有一个名为scrollpane的400 x 600滚动面板,后来用vbox动态填充,其中包含带文本的标签列表。

我想要做的是在此面板上添加一个旋转,使其看起来像星球大战的介绍文本。我已经设法获得滚动文本的动画,但是当试图在X_AXIS上旋转面板时,它不会按我的意愿执行。

目标:Panel that is rotated as if it was this text

目前My best attempt after spending hours transforming

scrollpane.getTransforms().add(new Rotate(50, 300, 200, 20, Rotate.X_AXIS));

正如您所看到的那样,文本瞄准了正确的角度,但控件本身实际上并未在X轴上旋转3d。 我需要添加什么才能从目前的状态变为理想的效果? (以绝对像素为单位的面板顶部与底部相比较宽)。

1 个答案:

答案 0 :(得分:3)

你把它向后旋转了;可能你没有看到轮换,因为你的代码中有其他错误。

这对我有用:

import javafx.application.Application;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.text.Font;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;

public class StarWarsScrollPane extends Application {

    private final String text = "It is a period of civil war. Rebel spaceships, "
            + "striking from a hidden base, have won their first victory against the evil Galactic Empire."
            + " During the battle, Rebel spies managed to steal secret plans to the Empire's ultimate weapon,"
            + " the DEATH STAR, an armored space station with enough power to destroy an entire planet."
            + " Pursued by the Empire's sinister agents, Princess Leia races home aboard her starship,"
            + " custodian of the stolen plans that can save her people and restore freedom to the galaxy....";

    @Override
    public void start(Stage primaryStage) {
        Label label = new Label(text);
        label.setWrapText(true);
        label.setFont(Font.font(18));
        ScrollPane crawler = new ScrollPane(label);
        crawler.setVbarPolicy(ScrollBarPolicy.NEVER);
        crawler.setFitToWidth(true);

        crawler.getTransforms().add(new Rotate(-50, 300, 200, 20, Rotate.X_AXIS));


        Scene scene = new Scene(crawler, 400, 400);
        scene.setCamera(new PerspectiveCamera());


        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
}

enter image description here

请注意,如果您真的想要滚动“抓取”文本,则实际上并不需要滚动窗格,但您可以使用文本节点并在动画中进行翻译。如果这样做,请务必在添加旋转后添加转换:转换以相反的顺序应用(就好像你正确地乘以仿射变换矩阵一样)。

这是一个例子;)

import java.util.Random;

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Rectangle2D;
import javafx.scene.Cursor;
import javafx.scene.DepthTest;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;

public class StarWarsCrawler extends Application {

    private final String text = "It is a period of civil war. Rebel spaceships, "
            + "striking from a hidden base, have won their first victory against the evil Galactic Empire.\n\n"
            + "During the battle, Rebel spies managed to steal secret plans to the Empire's ultimate weapon,"
            + " the DEATH STAR, an armored space station with enough power to destroy an entire planet.\n\n"
            + "Pursued by the Empire's sinister agents, Princess Leia races home aboard her starship,"
            + " custodian of the stolen plans that can save her people and restore freedom to the galaxy....";

    @Override
    public void start(Stage primaryStage) {
        Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds();
        int width = (int) primaryScreenBounds.getWidth() ;
        int height = (int) primaryScreenBounds.getHeight() ;

        Text textNode = createText(width);

        Translate translate = new Translate();
        textNode.getTransforms().add(new Rotate(-60, 300, height/2, height/30, Rotate.X_AXIS));
        textNode.getTransforms().add(translate);

        Timeline animation = new Timeline(
                new KeyFrame(Duration.seconds(45), new KeyValue(translate.yProperty(), -10*height))
        );
        textNode.setTranslateY(2*height);

        StackPane root = new StackPane();

        generateStarField(width, height, root);

        root.getChildren().add(textNode);

        Scene scene = createScene(root);

        primaryStage.setFullScreenExitHint("");
        primaryStage.setFullScreen(true);
        primaryStage.setScene(scene);
        primaryStage.show();

        animation.play();
        animation.setOnFinished(e -> Platform.exit());
    }

    private Scene createScene(StackPane root) {
        Scene scene = new Scene(root, Color.BLACK);
        PerspectiveCamera camera = new PerspectiveCamera();
        camera.setDepthTest(DepthTest.ENABLE);
        scene.setCamera(camera);
        scene.setCursor(Cursor.NONE);
        scene.setOnMouseClicked(e -> {
            if (e.getClickCount() ==2) {
                Platform.exit();
            }
        });
        return scene;
    }

    private Text createText(int width) {
        Text textNode = new Text(text);
        textNode.setWrappingWidth(width*1.25);
        textNode.setFont(Font.font("Franklin Gothic", width/12));
        textNode.setFill(Color.rgb(229, 177, 58));
        return textNode;
    }

    private void generateStarField(int width, int height, StackPane root) {
        int numStars = width * height / 900 ;

        Random rng = new Random();
        for (int i = 1 ; i <= numStars ; i++) {
            double hue = rng.nextDouble() * 360 ;
            double saturation = rng.nextDouble() * 0.1 ;
            Color color = Color.hsb(hue, saturation, 1.0);
            Circle circle = new Circle(rng.nextInt(width), rng.nextInt(height), 2*rng.nextDouble(), color);
            circle.setManaged(false);
            circle.setTranslateZ(rng.nextDouble() * height * 1.25);
            root.getChildren().add(circle);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}