Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate LinearGradient on JavaFX?

I am trying to animate the text fill of a Label on JavaFX (Using JavaFX 8). My goal is to make the First color of the gradient to change from yellow to red every half second. I have tried this:

Timeline timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
timeline.setAutoReverse(true);

LinearGradient fill1 = new LinearGradient(50,50,200,200,false, CycleMethod.NO_CYCLE, new Stop(0.1f, Color.YELLOW), new Stop(1.0f, Color.BLACK));
LinearGradient fill2 = new LinearGradient(50,50,200,200,false, CycleMethod.NO_CYCLE, new Stop(0.1f, Color.RED), new Stop(1.0f, Color.BLACK));
KeyValue keyValue1 = new KeyValue(labelInstrucoes.textFillProperty(), fill1, Interpolator.EASE_OUT);
KeyValue keyValue2 = new KeyValue(labelInstrucoes.textFillProperty(), fill2, Interpolator.EASE_OUT);

KeyFrame keyframe1 = new KeyFrame(Duration.millis(0), keyValue1);
KeyFrame keyframe2 = new KeyFrame(Duration.millis(500), keyValue2);

timeline.getKeyFrames().addAll(keyframe1, keyframe2);

timeline.play();

But it didn't work. However, if instead of LinearGradient i use a simple color, like this:

KeyValue keyValue1 = new KeyValue(labelInstrucoes.textFillProperty(), Color.YELLOW, Interpolator.EASE_OUT);
KeyValue keyValue2 = new KeyValue(labelInstrucoes.textFillProperty(), Color.RED, Interpolator.EASE_OUT);

It works. So, how to animate the gradient?

like image 902
Mateus Viccari Avatar asked Dec 14 '22 21:12

Mateus Viccari


1 Answers

You can use a css trick for this, using looked-up colors.

In an external CSS file, define a looked-up color for the beginning of the linear gradient, and define the text fill using a linear gradient that references the looked-up color:

animated-gradient.css:

.animated-gradient {
    -gradient-base: red ;
    -fx-text-fill: linear-gradient(to right, -gradient-base, black);
}

Then "animate" a color property, and update the inline style to change the value of the looked-up color whenever the property changes:

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;



public class AnimatedGradient extends Application {
    @Override
    public void start(Stage primaryStage) {
        StackPane root = new StackPane();
        Label label = new Label("Animated gradient");
        root.getChildren().add(label);
        label.getStyleClass().add("animated-gradient");
        Scene scene = new Scene(root,400,400);
        scene.getStylesheets().add(getClass().getResource("animated-gradient.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();

        ObjectProperty<Color> baseColor = new SimpleObjectProperty<>();

        KeyValue keyValue1 = new KeyValue(baseColor, Color.RED);
        KeyValue keyValue2 = new KeyValue(baseColor, Color.YELLOW);
        KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
        KeyFrame keyFrame2 = new KeyFrame(Duration.millis(500), keyValue2);
        Timeline timeline = new Timeline(keyFrame1, keyFrame2);

        baseColor.addListener((obs, oldColor, newColor) -> {
            label.setStyle(String.format("-gradient-base: #%02x%02x%02x; ", 
                    (int)(newColor.getRed()*255),
                    (int)(newColor.getGreen()*255),
                    (int)(newColor.getBlue()*255)));
        });

        timeline.setAutoReverse(true);
        timeline.setCycleCount(Animation.INDEFINITE);
        timeline.play();

    }

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

(You can use Bindings.format(...) instead of the listener, not much difference.)

like image 194
James_D Avatar answered Dec 21 '22 23:12

James_D