【问题标题】:Rotate scrollpane over the X-axis in javafx - star wars like effect在 javafx 中在 X 轴上旋转滚动窗格 - 类似星球大战的效果
【发布时间】:2017-01-16 22:08:45
【问题描述】:

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

我有一个场景,其中心是一个 400 x 600 的滚动面板,名为 scrollpane,后来动态填充了一个包含文本标签列表的 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 旋转。 为了从我目前拥有的效果达到预期效果,我需要添加什么? (与底部相比,面板顶部的绝对像素宽度较小)。

【问题讨论】:

  • 这里你需要两个属性,一个斜体格式和缩放,文本越靠近ScrollPane的顶部越小,越靠近下部越大得到。
  • 也许应用透视变换效果会起作用:PerspectiveTransform
  • 可能你没有设置相机...?如果没有完整的示例,很难知道为什么它不起作用。

标签: java javafx user-controls transform


【解决方案1】:

您已将其向后旋转;可能您没有看到轮换,因为您的代码中还有其他问题。

这对我有用:

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);
    }
}

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

这是一个例子;)

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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2012-12-26
    • 2022-11-29
    • 1970-01-01
    相关资源
    最近更新 更多