Статьи

Одновременные анимированные текстовые строки в JavaFX 2

Я решил запустить простой анимированный образец JavaFX 2, когда посетители вошли в комнату для моей презентации RMOUG Training Days 2012 . Желаемый результат был достигнут, когда участники спросили, было ли реализовано работающее приложение. Несколько человек были удивлены тем, что это было реализовано в «чистой Java» без Flash или HTML5. Я предоставляю исходный код для этого простого примера вместе с некоторыми снимками экрана в этом посте. Попутно этот пример демонстрирует анимацию нескольких экземпляров Text вдоль пути одновременно.

Ранее я писал в блоге об анимации по заданному пути с помощью PathTransition . Я адаптировал этот пример к этому новому примеру, изменив движущуюся фигуру с круга на текстовую «фигуру» и сделав так, чтобы три из этих «фигур» двигались по траектории одновременно через ParallelTransition .

Чтобы добавить немного больше к демонстрации, в этом примере я также использовал эффекты JavaFX , размер шрифта и спецификацию, а также раскраску символов. Список кодов для всего простого демонстрационного примера показан ниже.

RmougTd2012Animation.java

package dustin.examples;

import javafx.animation.ParallelTransition;
import javafx.animation.PathTransition;
import javafx.animation.PathTransition.OrientationType;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.Glow;
import javafx.scene.effect.Reflection;
import javafx.scene.paint.Color;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.Shape;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextBuilder;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * Simple animation of labels related to RMOUG Training Days 2012 using JavaFX.
 * 
 * @author Dustin
 */
public class RmougTd2012Animation extends Application
{
   /**
    * Generate Path upon which animation will occur.
    * 
    * @return Generated path.
    */
   private Path generateCurvyPath()
   {
      final Path path = new Path();
      path.getElements().add(new MoveTo(70,20));
      path.getElements().add(new CubicCurveTo(430, 0, 430, 120, 250, 120));
      path.getElements().add(new CubicCurveTo(50, 120, 50, 240, 430, 240));
      path.setOpacity(0.0);
      return path;
   }

   /**
    * Generate the path transition.
    * 
    * @param shape Shape to travel along path.
    * @param path Path to be traveled upon.
    * @param duration Duration of single animation.
    * @param delay Delay before beginning first animation.
    * @param orientation Orientation of shape during animation.
    * @return PathTransition.
    */
   private PathTransition generatePathTransition(
      final Shape shape, final Path path,
      final Duration duration, final Duration delay,
      final OrientationType orientation)
   {
      final PathTransition pathTransition = new PathTransition();
      pathTransition.setDuration(duration);
      pathTransition.setDelay(delay);
      pathTransition.setPath(path);
      pathTransition.setNode(shape);
      pathTransition.setOrientation(orientation);
      pathTransition.setCycleCount(Timeline.INDEFINITE);
      pathTransition.setAutoReverse(true);
      return pathTransition;
   }

   /**
    * Generate RMOUG text string with appropriate fill, font, and effect.
    * 
    * @return "RMOUG" text string with fill, font, and effect.
    */
   private Text generateRmougText()
   {
      return TextBuilder.create().text("RMOUG").x(20).y(20).fill(Color.DARKGRAY)
                        .font(Font.font(java.awt.Font.SERIF, 75))
                        .effect(new Glow(0.25)).build();
   }

   /**
    * Generate "Training Days 2012" text string with appropriate position, fill,
    * and font.
    * 
    * @return "Training Days 2012" with specified font, fill, and position.
    */
   private Text generateTrainingDaysText()
   {
      return TextBuilder.create().text("Training Days 2012")
                        .x(380).y(240).fill(Color.DARKOLIVEGREEN)
                        .font(Font.font(java.awt.Font.SERIF, 50)).build();
   }

   /**
    * Location String with specifed effect, font, and position.
    * 
    * @return Location String with specified effect, font, and position.
    */
   private Text generateDenverText()
   {
      final Reflection reflection = new Reflection();
      reflection.setFraction(1.0);
      return TextBuilder.create()
                        .text("Denver, Colorado").x(20).y(20)
                        .font(Font.font(java.awt.Font.SANS_SERIF, 25))
                        .effect(reflection)
                        .build();
   }

   /**
    * Apply animation.
    *  
    * @param group Group to which animation is to be applied.
    */
   private void applyAnimation(final Group group)
   {
      final Path path = generateCurvyPath();
      group.getChildren().add(path);
      final Shape rmoug = generateRmougText();
      group.getChildren().add(rmoug);
      final Shape td = generateTrainingDaysText();
      group.getChildren().add(td);
      final Shape denver = generateDenverText();
      group.getChildren().add(denver);
      final PathTransition rmougTransition =
         generatePathTransition(
            rmoug, path, Duration.seconds(8.0), Duration.seconds(0.5),
            OrientationType.NONE);
      final PathTransition tdTransition =
         generatePathTransition(
            td, path, Duration.seconds(5.5), Duration.seconds(0.1),
            OrientationType.NONE);
      final PathTransition denverTransition =
         generatePathTransition(
            denver, path, Duration.seconds(30), Duration.seconds(3),
            OrientationType.ORTHOGONAL_TO_TANGENT);
      final ParallelTransition parallelTransition =
         new ParallelTransition(rmougTransition, tdTransition, denverTransition);
      parallelTransition.play(); 
   }

   /**
    * JavaFX Application starting method.
    * 
    * @param stage Primary stage.
    * @throws Exception Potential JavaFX application exception.
    */
   @Override
   public void start(Stage stage) throws Exception
   {
      final Group rootGroup = new Group();
      final Scene scene = new Scene(rootGroup, 500, 400, Color.GHOSTWHITE);
      stage.setScene(scene);
      stage.setTitle("JavaFX 2 RMOUG Training Days 2012 Animations");
      stage.show();
      applyAnimation(rootGroup);
   }

   /**
    * Main function for running JavaFX animation demo.
    * 
    * @param arguments Command-line arguments; none expected.
    */
   public static void main(final String[] arguments)
   {
      Application.launch(arguments);
   }
}

Следующая серия снимков экрана пытается дать представление о том, как это выглядит при его выполнении.

Этот пример демонстрирует, что текст может быть анимирован вдоль пути, а также демонстрирует разницу между типами OrientationType NONE и ORTHOGONAL_TO_TANGENT . Первая спецификация ориентации имеет текст, обращенный вверх с абсолютистской точки зрения, в то время как последняя смещает направление текста в соответствии с поворотами пути. Javadoc для каждого типа обеспечивает более точное объяснение, где NONE определяется как «Матрица вращения целевого узла остается неизменной вдоль геометрического пути», тогда как ORTHOGONAL_TO_TANGENT определяется как «Матрица вращения целевого узла устанавливается так, чтобы держать узел перпендикулярно касательной к траектории пути вдоль геометрический путь. «

Для меня более интересной частью этого примера является то, как легко задать несколько анимаций, которые будут выполняться параллельно. Как показывает метод applyAnimation примера кода, три текстовых строки связаны с тремя различными экземплярами PathTransition . Хотя каждый из этих трех экземпляров PathTransition использует один и тот же путь , время начала и продолжительность каждого перехода различаются. Ни один из экземпляров PathTransition не имеет своих отдельных методов play (). Скорее, каждый связан с одним ParallelTransitionэкземпляр, и это тот метод play () экземпляра ParallelTransition, который вызывается. Поскольку три экземпляра PathTransition были связаны с экземпляром ParallelTransition, вызов функции play () для него вызывает play () для всех трех отдельных экземпляров PathTransition параллельно.

Вывод

JavaFX 2 позволяет легко выполнять несколько переходов параллельно. Один просто устанавливает каждый отдельный переход предпочтительным образом, а затем связывает каждый из этих переходов с экземпляром ParallelTransition и вызывает метод play () для этого экземпляра ParallelTransition. Анимация не ограничивается фигурами, но может использоваться и для текста.

 

От http://marxsoftware.blogspot.com/2012/02/javafx-2-simrallelous-animated-text.html