Язык программирования:
Java
Среда программирования:
IntelliJ IDEA 15.0.4
package me.grafika.barbanyagra; import javafx.animation.*; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.paint.Color; import javafx.scene.shape.*; import javafx.stage.Stage; import javafx.util.Duration; public class RainbowSpinners extends Application { final int ANIMATION_DURATION_MS = 4900; // время выполнения полного цикла анимации в миллисекундах final int SINGLE_SWAP_DURATION_MS = 1900; // время вращения одного кружка public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) throws Exception { Group root = new Group(); // корневой элемент сцены primaryStage.setTitle("Rainbow spinners"); // заголовок окна primaryStage.setScene(new Scene(root, 500, 500, Color.BLACK)); // если заменить фоновый цвет сцены с BLACK на WHITE, то можно посмотреть на траектории primaryStage.setResizable(false); // запрещаем изменять размер окна // цвета исходных кружков Color[] colors = new Color[24]; colors[0] = Color.web("#00fe03"); colors[1] = Color.web("#00ff3f"); colors[2] = Color.web("#00ff7f"); colors[3] = Color.web("#00ffbf"); colors[4] = Color.web("#00fbfe"); colors[5] = Color.web("#00bfff"); colors[6] = Color.web("#007fff"); colors[7] = Color.web("#003fff"); colors[8] = Color.web("#0000ff"); colors[9] = Color.web("#3f00ff"); colors[10] = Color.web("#7f00ff"); colors[11] = Color.web("#bf00ff"); colors[12] = Color.web("#fe00ff"); colors[13] = Color.web("#ff00bf"); colors[14] = Color.web("#ff007f"); colors[15] = Color.web("#ff003f"); colors[16] = Color.web("#ff0000"); colors[17] = Color.web("#ff3f00"); colors[18] = Color.web("#ff7f00"); colors[19] = Color.web("#ffbf00"); colors[20] = Color.web("#fffe00"); colors[21] = Color.web("#bfff00"); colors[22] = Color.web("#7fff00"); colors[23] = Color.web("#3fff00"); Group circles = new Group(); // группа для хранения кругов Group paths = new Group(); // группа для хранения траекторий (нужно для просмотра траекторий) // создаем массив анимаций, в который сохраним описание анимации для каждого кружка SequentialTransition[] cycles = new SequentialTransition[24]; for (int i = 0; i < 24; i++) { // создаем круг Circle circle = new Circle(getX(i), getY(i), 14, colors[i]); circle.setStroke(Color.TRANSPARENT); // делаем обрамление невидимым circles.getChildren().add(circle); // добавляем круг в группу Path path; // класс Path описывает траекторию движения int paired; // для каждого круга определим, на место круга с каким индексом он движется if (i % 2 == 0) { // четные кружки движутся от центра сцены, нечетные - к центру paired = (i + 3) % 24; double angle = Math.PI / 6 + i * 2 * Math.PI / 24; path = new Path( // описание "внешней" траектории с помощью квадратичной кривой Безье new MoveTo(getX(i), getY(i)), new QuadCurveTo(250 + Math.cos(angle) * 265, 250 + Math.sin(angle) * 265, getX(paired), getY(paired)) ); } else { paired = (i - 3 + 24) % 24; path = new Path( // описание "внутренней" траектории с помощью дуги new MoveTo(getX(i), getY(i)), new ArcTo(1, 1, 0, getX(paired), getY(paired), true, true) ); } paths.getChildren().add(path); // добавляем траекторию в группу // создаем изменение расположения кружка PathTransition pt = new PathTransition(Duration.millis(SINGLE_SWAP_DURATION_MS), path, circle); pt.setInterpolator(Interpolator.EASE_BOTH); // выбираем интерполятор, ускоряющийся в начале, и замедляющийся в конце изменения // создаем изменение цвета кружка FillTransition ft = new FillTransition(Duration.millis(SINGLE_SWAP_DURATION_MS), circle, colors[i], colors[paired]); ft.setInterpolator(Interpolator.EASE_BOTH); // создаем последовательное изменение SequentialTransition cycle = new SequentialTransition(); cycle.getChildren().addAll( new ParallelTransition(pt, ft), // одновременно выполняем изменения расположения и цвета new PauseTransition(Duration.millis(ANIMATION_DURATION_MS - SINGLE_SWAP_DURATION_MS)) // пауза ); cycle.setCycleCount(Animation.INDEFINITE); // указываем, что оно должно выполняться неограниченное число раз cycles[i] = cycle; // сохраняем итоговое описание анимации кружка } root.getChildren().add(paths); // добавляем в корневую группу траектории root.getChildren().add(circles); // добавляем в корневую группу круги primaryStage.show(); // запускаем сцену for (int i = 0; i < 24; i += 2) { // проматываем анимацию, чтобы круги не выстраивались в большой круг одновременно cycles[i].jumpTo(Duration.millis(ANIMATION_DURATION_MS - i / 2 * ANIMATION_DURATION_MS / 12.)); cycles[(i + 3) % 24].jumpTo(Duration.millis(ANIMATION_DURATION_MS - i / 2 * ANIMATION_DURATION_MS / 12.)); } for (int i = 0; i < 24; i += 2) { // запускаем анимацию cycles[i].play(); cycles[(i + 3) % 24].play(); } } // Функция получения абсцисс-координаты i-го кружка на большой окружности private double getX(int i) { double angle = 2 * Math.PI / 48 + i * (2 * Math.PI / 24); return 250 + Math.cos(angle) * 150; } // Функция получения ординат-координаты i-го кружка на большой окружности private double getY(int i) { double angle = 2 * Math.PI / 48 + i * (2 * Math.PI / 24); return 250 + Math.sin(angle) * 150; } }
Прикрепленный файл | Размер |
---|---|
RainbowSpinners.zip | 36.09 кб |