我正在尝试在JavaFX上使用Label的文本填充动画(使用JavaFX 8)。 我的目标是使渐变的第一种颜色每半秒从黄色变为红色。 我试过这个:
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();
但它没有用。但是,如果不使用LinearGradient,我会使用简单的颜色,如下所示:
KeyValue keyValue1 = new KeyValue(labelInstrucoes.textFillProperty(), Color.YELLOW, Interpolator.EASE_OUT);
KeyValue keyValue2 = new KeyValue(labelInstrucoes.textFillProperty(), Color.RED, Interpolator.EASE_OUT);
有效。那么,如何为渐变设置动画?
答案 0 :(得分:7)
你可以使用查找颜色来使用css技巧。
在外部CSS文件中,为线性渐变的开头定义一个查找颜色,并使用引用查找颜色的线性渐变定义文本填充:
动画-gradient.css:
.animated-gradient {
-gradient-base: red ;
-fx-text-fill: linear-gradient(to right, -gradient-base, black);
}
然后“设置”颜色属性的“动画”,并更新内联样式,以便在属性更改时更改查找颜色的值:
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);
}
}
(您可以使用Bindings.format(...)
代替听众,但差别不大。)
答案 1 :(得分:2)
这是一个没有css的解决方案。它可以在动画控件中使用。 下面我发布了两个不同元素的Application代码。你可以运行它,看看它是如何工作的。
public class FilledRegion extends Region {
private final Random rand;
private ObjectProperty<Color> externalColor = new SimpleObjectProperty();
private ObjectProperty<Color> internalColor = new SimpleObjectProperty();
private Color oldExternalColor;
private Color oldInternalColor;
private Background bg;
private Timeline timeline;
private int duration;
public FilledRegion() {
rand = new Random();
this.setMinWidth(75);
oldExternalColor = getRandomColor(AnimatedGradients.baseExternalColor, AnimatedGradients.externalDelta);
oldInternalColor = getRandomColor(AnimatedGradients.baseInternalColor, AnimatedGradients.internalDelta);
externalColor.set( oldExternalColor );
internalColor.set( oldInternalColor );
setBackground();
internalColor.addListener((obs, oldColor, newColor) -> {
setBackground();
});
}
public void startAnimation() {
timeline = new Timeline();
createTimelineContent();
timeline.setOnFinished(ActionEvent -> {
createTimelineContent();
timeline.play();
});
timeline.play();
}
private void createTimelineContent() {
timeline.getKeyFrames().clear();
duration = getRandomDuration();
KeyFrame kf1 =
new KeyFrame(Duration.ZERO,
new KeyValue( externalColor, oldExternalColor ),
new KeyValue( internalColor, oldInternalColor ));
oldExternalColor = getRandomColor(AnimatedGradients.baseExternalColor, AnimatedGradients.externalDelta);
oldInternalColor = getRandomColor(AnimatedGradients.baseInternalColor, AnimatedGradients.internalDelta);
KeyFrame kf2 =
new KeyFrame(new Duration(duration),
new KeyValue( externalColor, oldExternalColor ),
new KeyValue( internalColor, oldInternalColor ));
timeline.getKeyFrames().addAll( kf1, kf2 );
}
private void setBackground() {
bg = new Background(
new BackgroundFill(
new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE,
new Stop[] { new Stop(0, externalColor.get()), new Stop(0.5, internalColor.get()), new Stop(1, externalColor.get())}
),
new CornerRadii(0),
new Insets(0, 0, 0, 0)
)
);
this.setBackground(bg);
}
private Color getRandomColor(Color color, double delta) {
int index = (int)( (color.getRed()+getRandomCoefficient(delta))*255 );
int r = ( index > 255 ) ? 255 : ( (index < 0) ? 0 : index );
index = (int)( (color.getGreen()+getRandomCoefficient(delta))*255 );
int g = ( index > 255 ) ? 255 : ( (index < 0) ? 0 : index );
index = (int)( (color.getBlue()+getRandomCoefficient(delta))*255 );
int b = ( index > 255 ) ? 255 : ( (index < 0) ? 0 : index );
return Color.rgb(r, g, b);
}
private double getRandomCoefficient(double delta) {
return ( rand.nextDouble()*2 - 1 ) * delta;
}
private int getRandomDuration() {
return (int)(( rand.nextDouble()*2 - 1 ) * AnimatedGradients.durationDelta * AnimatedGradients.baseDuration) + AnimatedGradients.baseDuration;
}}
public class AnimatedIcon extends WritableImage {
private ObjectProperty<Color> topColor = new SimpleObjectProperty();
private ObjectProperty<Color> bottomColor = new SimpleObjectProperty();
private Color oldTopColor;
private Color oldBottomColor;
private Timeline timeline;
private static final int DURATION = 5000;
private static final Random rand = new Random();
private static final int ICON_WIDTH = 32;
private static final int ICON_HEIGHT = 32;
private Stage primaryStage;
public AnimatedIcon(Stage primaryStage) {
super(ICON_WIDTH, ICON_HEIGHT);
this.primaryStage = primaryStage;
oldTopColor = Color.rgb(0, 45, 0);
oldBottomColor = Color.rgb(12, 128, 12);
topColor.set(oldTopColor);
bottomColor.set(oldBottomColor);
createGraphics();
bottomColor.addListener((obs, oldColor, newColor) -> {
createGraphics();
});
}
private void createGraphics() {
PixelWriter pixelWriter = this.getPixelWriter();
for (int y = 0; y < ICON_HEIGHT; y++) {
for (int x = 0; x < ICON_WIDTH; x++) {
double position = (double)x/(double)ICON_WIDTH;
int r = (int)( ( topColor.get().getRed() - (topColor.get().getRed() - bottomColor.get().getRed())*position ) * 255 );
int g = (int)( ( topColor.get().getGreen() - (topColor.get().getGreen() - bottomColor.get().getGreen())*position ) * 255 );
int b = (int)( ( topColor.get().getBlue() - (topColor.get().getBlue() - bottomColor.get().getBlue())*position ) * 255 );
double o = topColor.get().getOpacity() - (topColor.get().getOpacity() - bottomColor.get().getOpacity())*position;
pixelWriter.setColor(x,y,Color.rgb(r,g,b,o));
}
}
int index = primaryStage.getIcons().indexOf(this);
if (index == 0) {
primaryStage.getIcons().set(index, this);
} else {
primaryStage.getIcons().add(this);
}
}
public void startAnimation() {
timeline = new Timeline();
createTimelineContent();
timeline.setOnFinished(ActionEvent -> {
createTimelineContent();
timeline.play();
});
timeline.play();
}
private void createTimelineContent() {
timeline.getKeyFrames().clear();
KeyFrame kf1 =
new KeyFrame(Duration.ZERO,
new KeyValue( topColor, oldTopColor ),
new KeyValue( bottomColor, oldBottomColor ));
oldTopColor = Color.rgb(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256), rand.nextDouble());
oldBottomColor = Color.rgb(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256), 1);
KeyFrame kf2 =
new KeyFrame(new Duration(DURATION),
new KeyValue( topColor, oldTopColor ),
new KeyValue( bottomColor, oldBottomColor ));
timeline.getKeyFrames().addAll( kf1, kf2 );
}}
public class AnimatedGradients extends Application {
protected static int baseDuration = 10000;
protected static Color baseExternalColor = Color.rgb(0, 0, 0);
protected static Color baseInternalColor = Color.rgb(127, 127, 127);
protected static double durationDelta = 0.25;
protected static double externalDelta = 0.1;
protected static double internalDelta = 1;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
HBox root = new HBox();
root.setSpacing(1);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 761, 500, Color.BLACK);
primaryStage.setScene(scene);
AnimatedIcon ai = new AnimatedIcon(primaryStage);
primaryStage.getIcons().add(ai);
ai.startAnimation();
primaryStage.setTitle("Animated Gradients");
for (int i = 0; i < 10; i++) {
FilledRegion gr = new FilledRegion();
root.getChildren().add(gr);
gr.startAnimation();
}
primaryStage.show();
}}