通過更改節(jié)點(diǎn)的屬性(如大小,位置和顏色等)創(chuàng)建動畫。
時(shí)間軸動畫會隨著時(shí)間的推移更新屬性值。
JavaFX支持關(guān)鍵幀動畫。動畫狀態(tài)場景在某些時(shí)間由開始和結(jié)束關(guān)鍵幀聲明。
JavaFX允許我們創(chuàng)建可以內(nèi)插的定時(shí)事件預(yù)定義的值來生成動畫。
例如,為了產(chǎn)生淡出效果,我們將目標(biāo)為節(jié)點(diǎn)的不透明屬性來內(nèi)插其值,從完全不透明的1開始到在一段時(shí)間內(nèi)是透明的0。
以下代碼定義了一個(gè)KeyValue,它以從1開始并以0結(jié)尾的矩形的不透明度屬性為目標(biāo)。
Rectangle rectangle = new Rectangle(0, 0, 50, 50); KeyValue keyValue = new KeyValue(rectangle.opacityProperty(), 0);
KeyValue對象實(shí)際上不內(nèi)插值。它定義屬性的開始和結(jié)束值。
默認(rèn)情況下,KeyValue對象將有一個(gè)線性插值器。
KeyValue可以用不同的方式定義類型的內(nèi)插器,如線性,ease in, 或ease out。
以下代碼定義了一個(gè)鍵值,它將使用Interpolator.EASE_OUT內(nèi)插器從左到右將矩形動畫化100像素。漸弱將減慢結(jié)束鍵值之前的漸變。
Rectangle rectangle = new Rectangle(0, 0, 50, 50); KeyValue keyValue = new KeyValue(rectangle.xProperty(), 100, Interpolator.EASE_OUT);
當(dāng)動畫發(fā)生時(shí),每個(gè)步驟稱為由KeyFrame對象定義的關(guān)鍵幀。
關(guān)鍵幀在javafx.util.Duration中定義的時(shí)間段內(nèi)插入在KeyValue對象中定義的鍵值。
當(dāng)創(chuàng)建KeyFrame對象時(shí),構(gòu)造函數(shù)需要一個(gè)定時(shí)持續(xù)時(shí)間(Duration)。KeyFrame構(gòu)造函數(shù)接受一個(gè)或多個(gè)鍵值。
假設(shè)我們要從左上角到右下角移動一個(gè)矩形,我們定義一個(gè)具有1000毫秒持續(xù)時(shí)間的關(guān)鍵幀和兩個(gè)表示矩形的x和y屬性的關(guān)鍵值。
以下代碼定義關(guān)鍵幀,以一秒或1000毫秒將矩形的左上角(0,0)移動到點(diǎn)(100,100)。
Rectangle rectangle = new Rectangle(0, 0, 50, 50); KeyValue xValue = new KeyValue(rectangle.xProperty(), 100); KeyValue yValue = new KeyValue(rectangle.yProperty(), 100); KeyFrame keyFrame = new KeyFrame(Duration.millis(1000), xValue, yValue);
時(shí)間軸是由許多KeyFrame對象組成的一個(gè)動畫序列。每個(gè)KeyFrame對象按順序運(yùn)行。
時(shí)間軸是javafx.animation.Animation類的子類,它具有標(biāo)準(zhǔn)屬性,如循環(huán)計(jì)數(shù)和自動反轉(zhuǎn)。
循環(huán)計(jì)數(shù)是播放動畫的次數(shù)。要無限期地播放動畫,請使用值Timeline.INDEFINITE。
auto-reverse
屬性是一個(gè)布爾標(biāo)志,表示動畫可以向后播放時(shí)間軸。
默認(rèn)情況下,周期計(jì)數(shù)設(shè)置為1,自動反轉(zhuǎn)設(shè)置為false。
要向時(shí)間軸對象添加關(guān)鍵幀,請使用getKeyFrames().addAll()方法。
以下代碼演示了自動反轉(zhuǎn)設(shè)置為true時(shí)無限期播放的時(shí)間軸。
Timeline timeline = new Timeline(); timeline.setCycleCount(Timeline.INDEFINITE); timeline.setAutoReverse(true); timeline.getKeyFrames().addAll(keyFrame1, keyFrame2); timeline.play();
/* * Copyright (c) 2011, 2012 Oracle and/or its affiliates. * All rights reserved. Use is subject to license terms. * * This file is available and licensed under the following license: * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //package colorfulcircles; import javafx.animation.KeyFrame; import javafx.animation.KeyValue; import javafx.animation.Timeline; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.effect.BlendMode; import javafx.scene.effect.BoxBlur; import javafx.scene.paint.Color; import javafx.scene.paint.CycleMethod; import javafx.scene.paint.LinearGradient; import javafx.scene.paint.Stop; import javafx.scene.shape.Circle; import javafx.scene.shape.Rectangle; import javafx.scene.shape.StrokeType; import javafx.stage.Stage; import javafx.util.Duration; import static java.lang.Math.random; public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { Group root = new Group(); Scene scene = new Scene(root, 800, 600, Color.BLACK); primaryStage.setScene(scene); Group circles = new Group(); for (int i = 0; i < 30; i++) { Circle circle = new Circle(150, Color.web("white", 0.05)); circle.setStrokeType(StrokeType.OUTSIDE); circle.setStroke(Color.web("white", 0.16)); circle.setStrokeWidth(4); circles.getChildren().add(circle); } Rectangle colors = new Rectangle(scene.getWidth(), scene.getHeight(), new LinearGradient(0f, 1f, 1f, 0f, true, CycleMethod.NO_CYCLE, new Stop[]{ new Stop(0, Color.web("#f8bd55")), new Stop(0.14, Color.web("#c0fe56")), new Stop(0.28, Color.web("#5dfbc1")), new Stop(0.43, Color.web("#64c2f8")), new Stop(0.57, Color.web("#be4af7")), new Stop(0.71, Color.web("#ed5fc2")), new Stop(0.85, Color.web("#ef504c")), new Stop(1, Color.web("#f2660f")),})); Group blendModeGroup = new Group(new Group(new Rectangle(scene.getWidth(), scene.getHeight(), Color.BLACK), circles), colors); colors.setBlendMode(BlendMode.OVERLAY); root.getChildren().add(blendModeGroup); circles.setEffect(new BoxBlur(10, 10, 3)); Timeline timeline = new Timeline(); for (Node circle : circles.getChildren()) { timeline.getKeyFrames().addAll( new KeyFrame(Duration.ZERO, // set start position at 0 new KeyValue(circle.translateXProperty(), random() * 800), new KeyValue(circle.translateYProperty(), random() * 600)), new KeyFrame(new Duration(40000), // set end position at 40s new KeyValue(circle.translateXProperty(), random() * 800), new KeyValue(circle.translateYProperty(), random() * 600))); } // play 40s of animation timeline.play(); primaryStage.show(); } }
上面的代碼生成以下結(jié)果。
/* * Copyright (c) 2011, Pro JavaFX Authors * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of JFXtras nor the names of its contributors may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Metronome1Main.fx - A simple example of animation using a Timeline * * Developed 2011 by James L. Weaver jim.weaver [at] javafxpert.com * as a JavaFX SDK 2.0 example for the Pro JavaFX book. */ import javafx.animation.AnimationTimer; import javafx.animation.KeyFrame; import javafx.animation.KeyValue; import javafx.animation.Timeline; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.effect.Lighting; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.scene.text.Text; import javafx.stage.Stage; import javafx.util.Duration; public class Main extends Application { //main timeline private Timeline timeline; private AnimationTimer timer; //variable for storing actual frame private Integer i=0; @Override public void start(Stage stage) { Group p = new Group(); Scene scene = new Scene(p); stage.setScene(scene); stage.setWidth(500); stage.setHeight(500); p.setTranslateX(80); p.setTranslateY(80); //create a circle with effect final Circle circle = new Circle(20, Color.rgb(156,216,255)); circle.setEffect(new Lighting()); //create a text inside a circle final Text text = new Text (i.toString()); text.setStroke(Color.BLACK); //create a layout for circle with text inside final StackPane stack = new StackPane(); stack.getChildren().addAll(circle, text); stack.setLayoutX(30); stack.setLayoutY(30); p.getChildren().add(stack); stage.show(); //create a timeline for moving the circle timeline = new Timeline(); timeline.setCycleCount(Timeline.INDEFINITE); timeline.setAutoReverse(true); //You can add a specific action when each frame is started. timer = new AnimationTimer() { @Override public void handle(long l) { text.setText(i.toString()); i++; } }; //create a keyValue with factory: scaling the circle 2times KeyValue keyValueX = new KeyValue(stack.scaleXProperty(), 2); KeyValue keyValueY = new KeyValue(stack.scaleYProperty(), 2); //create a keyFrame, the keyValue is reached at time 2s Duration duration = Duration.millis(2000); //one can add a specific action when the keyframe is reached EventHandler onFinished = new EventHandler<ActionEvent>() { public void handle(ActionEvent t) { stack.setTranslateX(java.lang.Math.random()*200-100); //reset counter i = 0; } }; KeyFrame keyFrame = new KeyFrame(duration, onFinished , keyValueX, keyValueY); //add the keyframe to the timeline timeline.getKeyFrames().add(keyFrame); timeline.play(); timer.start(); } public static void main(String[] args) { Application.launch(args); } }
上面的代碼生成以下結(jié)果。
更多建議: