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?
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With