如何为JavaFX中的文本节点的字体大小设置动画

时间:2018-06-24 20:03:03

标签: java javafx javafx-8

我想知道是否有一种方法可以动画化节点的文本大小(例如Label),例如通过过渡来更改文本大小?我尝试为节点的Timeline设置一个fontProperty(),但是什么都没有发生:

Label label = new Label(); // The text node
Font font = Font.font(100); // Change the text size to 100
Timeline timeline = new Timeline(
  new KeyFrame(Duration.ZERO, new KeyValue(label.fontProperty(), label.getFont())),
  new KeyFrame(Duration.millis(1000), new KeyValue(label.fontProperty(), font))
);

我唯一想到的方法是缩放节点的 ACTUAL 大小。但是不利的是,它也会改变节点的布局(位置随其大小而变化)。此外,如果您确实希望文本大小与特定的font-size值一样大/小,这是不准确的。

Label label = new Label(); // The text node
double size = 2; // Scale the size by 2
Timeline timeline = new Timeline(
  new KeyFrame(Duration.ZERO,
    new KeyValue(label.scaleXProperty(), label.getScaleX()),
    new KeyValue(label.scaleYProperty(), label.getScaleY())),
  new KeyFrame(Duration.millis(1000),
    new KeyValue(label.scaleXProperty(), size),
    new KeyValue(label.scaleYProperty(), size))
);

还有其他方法可以实现吗?


更新

此过渡中使用的公式(以防万一我忘记或丢失了源代码,所以我可以回到这里并在此处共享它。)

@Override
protected void interpolate(double frac) {

    // Determine which is less/greater value between the initial and
    // ending value, then get their difference. This is to resolve the
    // end value when we either increase or decrease the initial value.
    double min = Math.min(start, end); // returns the smaller value
    double max = Math.max(start, end); // returns the higher value
    double diff = max - min; // the positive difference between the two value.

    // Since our start will always be the initial value regardless if
    // it is greater or less than the end, we will simply increase or
    // decrease its value until it reaches the desired end value.
    // Also, computing the difference between their value was to determine
    // if they both have equal values, it means (max - min) is always 0
    // as well as multiplying it to frac, therefore, there will be a
    // 0 value to increase or decrease.
    double size = (start == min) ?
                   start + (diff * frac) : // start is smaller so we'll just increase its value
                   start - (diff * frac); // decrease if it has the higher value than end

    UIcontrol.setFont(Font.font(size));
}

1 个答案:

答案 0 :(得分:1)

这是一个实现自定义Interpolator的示例。

您可以在hereTransition类中探索其他方法。请注意那里的属性是从类javafx.animation.Animation继承的!

import javafx.animation.Interpolator;
import javafx.animation.Transition;
import javafx.scene.control.Labeled;
import javafx.scene.text.Font;
import javafx.util.Duration;

public class TextSizeTransition extends Transition{

    private Labeled UIcontrol; // a little generic -> subclasses: ButtonBase, Cell, Label, TitledPane
    private int start, end; // initial and final size of the text

    public TextSizeTransition(Labeled UIcontrol, int start, int end, Duration duration) {
        this.UIcontrol = UIcontrol;
        this.start = start;
        this.end = end - start; // minus start because of (end * frac) + start in interpolate() 
        setCycleDuration(duration);  
        setInterpolator(Interpolator.LINEAR); 
        //setCycleCount(100);
        // and a lot of other methods 
    }

    @Override
    protected void interpolate(double frac) {
        // frac value goes from 0 to 1
        // when frac is zero -> size is start
        // when frac is 1 -> size is end + start 
        //(that's why we this.end = end - start; above to back to original end value)
        int size = (int) ((end * frac) + start);
        if(size<=end) {
            UIcontrol.setFont(Font.font(size));
        }else { // once the size reaches the destination (i.e. end value)
            // back to the start size if you want
            //UIcontrol.setFont(Font.font(start));
        }
    }
}

示例

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.util.Duration;

public class TextAnimation extends Application {
  public static void main(String[] args) {
    Application.launch(args);
  }

  @Override
  public void start(Stage stage) {

    Label label = new Label("Text Size Animation");
    Pane root = new Pane(label);
    root.setPrefSize(1100, 300);
    Scene scene = new Scene(root);

    // transit text size from 10 to 100 during 5 seconds
    TextSizeTransition trans = new TextSizeTransition(label, 10, 100,Duration.millis(5000));

    stage.setScene(scene);
    stage.show();

    trans.play();
  }
}

结果

gif