Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a text color transition without CSS?

I've made a dummy project just to show what is trying to be made. I'm going for a transition on color for text without CSS (as I just can't wrap my head around CSS). In the dummy project, the text starts from red

enter image description here

then goes to blue

enter image description here

Found out about FillTransition though that only works with shapes, so this would be a similar function. My other attempt was trying to get the RGB values of both colors then stick them in a do while with a new Color just to test it out though the transition is almost instant as the application starts so it changes the color but without transitioning effect. I'm thinking of making an Timeline for this similar to the do while but I haven't tried that yet.

Before going into this what are some ways to make this effect?

Here's the dummy code:

package application;
    
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();

            Scene scene = new Scene(root,400,400);

            StackPane stack = new StackPane();
            
            Text text = new Text("Hello there StackOverflow, how are you? (:");
            
            Color color1 = Color.RED;
            Color color2 = Color.BLUE;
            
            double r1 = color1.getRed();
            double g1 = color1.getGreen();
            double b1 = color1.getBlue();
            
            double r2 = color2.getRed();
            double g2 = color2.getGreen();
            double b2 = color2.getBlue();
            
            Color colorEffect = new Color(r1, g1, b1, 1.0);
            
            stack.setLayoutX(200);
            stack.setLayoutY(200);
            
            text.setFont(Font.font(16));
            text.setFill(colorEffect);
            
            stack.getChildren().add(text);
            root.getChildren().add(stack);
            
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}
like image 346
Providence Avatar asked Oct 19 '25 12:10

Providence


2 Answers

Because Color implements Interpolatable, you can use it directly as a KeyValue in a Timeline, without the need for a custom interpolator.

image

import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * @see https://stackoverflow.com/a/74249258/230513
 */
public class FillAnimation extends Application {

    @Override
    public void start(Stage stage) {
        stage.setTitle("FillAnimation");
        var color1 = Color.RED;
        var color2 = Color.BLUE;
        var text = new Text("Hello, StackOverflow!");
        text.setFill(color1);
        text.setStyle("-fx-font-family: serif; -fx-font-size: 42;"
            + "-fx-font-style: oblique; -fx-font-weight: bold");
        var timeline = new Timeline();
        var c = new KeyValue(text.fillProperty(), color2, Interpolator.EASE_BOTH);
        var k = new KeyFrame(new Duration(1000), c);
        timeline.getKeyFrames().add(k);
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.setAutoReverse(true);
        var root = new StackPane(text);
        root.setPadding(new Insets(16));
        var scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
        timeline.play();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
like image 170
trashgod Avatar answered Oct 22 '25 01:10

trashgod


Text is a shape, so FillTransition works on text, because it operates on any kind of shape.

This effect demonstrated in this answer is the same as that demonstrated in trashgod's answer, (the code is based on trashgod's code), it just uses a transition rather than a timeline.

The example uses the default interpolator, EASE_BOTH, to interpolate between the interpolatable Color values, but you can set a custom interpolator if desired.

import javafx.animation.*;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class TextFillTransitionApp extends Application {

    @Override
    public void start(Stage stage) {
        var text = new Text("Hello, StackOverflow!");
        text.getStyleClass().add("styled-text");

        FillTransition textFillTransition = new FillTransition(
                Duration.seconds(1),
                text,
                Color.RED,
                Color.BLUE
        );

        textFillTransition.setCycleCount(Timeline.INDEFINITE);
        textFillTransition.setAutoReverse(true);

        var layout = new StackPane(text);
        layout.setPadding(new Insets(16));
        layout.getStylesheets().add(CSS);

        stage.setScene(new Scene(layout));
        stage.show();

        textFillTransition.play();
    }

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

    private static final String CSS_DATA = "data:text/css,";
    private static final String CSS = CSS_DATA + // language=CSS
            """
            .styled-text {
                -fx-font-family: serif;
                -fx-font-size: 42;
                -fx-font-style: oblique;
                -fx-font-weight: bold
            }
            """;
}
like image 43
jewelsea Avatar answered Oct 22 '25 03:10

jewelsea



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!