{"id":13777538,"url":"https://github.com/schlegel11/JFXAnimation","last_synced_at":"2025-05-11T11:33:53.256Z","repository":{"id":86789871,"uuid":"156935940","full_name":"schlegel11/JFXAnimation","owner":"schlegel11","description":"CSS keyframe animation for JavaFX. Create animations like you would do with CSS.","archived":false,"fork":false,"pushed_at":"2018-12-25T15:04:13.000Z","size":7596,"stargazers_count":52,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-02-12T17:03:22.229Z","etag":null,"topics":["animation","css","javafx","keyframe-animation"],"latest_commit_sha":null,"homepage":"http://jfxanimation.schlegel11.de","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/schlegel11.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-11-10T01:23:00.000Z","updated_at":"2024-02-12T17:03:22.230Z","dependencies_parsed_at":"2024-01-06T22:29:49.351Z","dependency_job_id":"d33817ef-ce6d-4324-a9e4-1c1223797e9e","html_url":"https://github.com/schlegel11/JFXAnimation","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schlegel11%2FJFXAnimation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schlegel11%2FJFXAnimation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schlegel11%2FJFXAnimation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schlegel11%2FJFXAnimation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schlegel11","download_url":"https://codeload.github.com/schlegel11/JFXAnimation/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224862977,"owners_count":17382287,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","css","javafx","keyframe-animation"],"created_at":"2024-08-03T18:00:45.033Z","updated_at":"2024-11-17T13:30:56.041Z","avatar_url":"https://github.com/schlegel11.png","language":"Java","funding_links":[],"categories":["Libraries, Tools and Projects"],"sub_categories":[],"readme":"# JFXAnimation\n\n[![Build Status](https://travis-ci.org/schlegel11/JFXAnimation.svg?branch=master)](https://travis-ci.org/schlegel11/JFXAnimation) [![Download](https://api.bintray.com/packages/schlegel11/JavaFX/jfxanimation/images/download.svg)](https://bintray.com/schlegel11/JavaFX/jfxanimation/_latestVersion) [![Maven Central](https://img.shields.io/maven-central/v/de.schlegel11/jfxanimation.svg)](https://search.maven.org/search?q=a:jfxanimation) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/64afe731cf254cf5b36f725a125f0c5e)](https://www.codacy.com/app/marcel_4/JFXAnimation?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=schlegel11/JFXAnimation\u0026utm_campaign=Badge_Grade)\n\nCSS keyframe animation for JavaFX.\u003cbr\u003e\nIf you are using [JFoenix](https://github.com/jfoenixadmin/JFoenix) JFXAnimation is included _(currently version 1.0.0 only)_\n\n## Requirements\n\n-   JDK 8 and up\n\n## Documentation\n\n### Version 2.0.0 (Latest)\n\nFor details see: [JavaDoc](https://schlegel11.github.io/JFXAnimation/releases/2.0.0/api/docs/)\n\n## Changelog\n\n\u003cdetails\u003e\u003csummary\u003eVersion 2.0.0\u003c/summary\u003e\n\n-   cleanup and refactored code\n\n- JFXAnimationTemplateConfig\n  -   add reverse method\n  -   [add dynamic interpolator](#dynamic-end-values-and-interpolators)\n  -   [add from/To automatic generation](#the-more-css-way)\n  -   [add automatic reset](#the-more-css-way)\n  -   [add fluent transition](#fluent-transition)\n  \n- JFXAnimationTemplateAction\n  -   [add dynamic end value/interpolator](#dynamic-end-values-and-interpolators)\n  -   [add fluent transition](#fluent-transition)  \n- JFXTemplateProcess\n  -   [add time method](#action-with-absolute-duration)\n  \n\u003c/details\u003e\n\n## Details\n\nThe JFXAnimation project provides the JFXAnimationTemplate classes, which acts as a builder for JavaFX animations.\u003cbr\u003e\nThe building structure of a JFXAnimationTemplate is based on CSS keyframe animations, which have some advantages:\n\n### Features\n\n-   Define the animation in a relative way, based on different percentage values, related to a total animation duration or with a default absolute time.\n-   Multiple target observers per action\n-   Define the animation in a complete lazy evaluated way\n-   Finish events for every step/action\n-   Specific or global interpolator for all animation actions\n-   Use dynamic end values or interpolators which can be exchanged at runtime\n-   Transfer your current CSS animations easily to JavaFX\n-   Create animations simply for multiple animation objects\n\n### Code comparison\n\n\u003cbr\u003e\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003cth colspan=\"3\"\u003e\n\nCSS [TADA](https://github.com/daneden/animate.css/blob/master/source/attention_seekers/tada.css) animation from [animate.css](https://daneden.github.io/animate.css/)\n\u003c/th\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd align=\"left\"\u003e\n\n[Implementation](https://github.com/fxexperience/code/blob/master/FXExperienceControls/src/com/fxexperience/javafx/animation/TadaTransition.java) with [Keyframe](https://docs.oracle.com/javafx/2/api/javafx/animation/KeyFrame.html) objects\n\u003c/td\u003e\n\u003ctd align=\"left\"\u003e\n\nImplementation with [JFXAnimationTemplate](https://schlegel11.github.io/JFXAnimation/releases/1.0.0/api/docs/de/schlegel11/jfxanimation/JFXAnimationTemplate.html)\n\u003c/td\u003e\n\u003ctd align=\"left\"\u003e\n\n[Implementation](https://github.com/daneden/animate.css/blob/master/source/attention_seekers/tada.css) with pure CSS\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd valign=\"top\" align=\"left\"\u003e\n\u003cpre lang=\"java\"\u003e\nTimelineBuilder.create()\n                .keyFrames(\n                    new KeyFrame(Duration.millis(0),    \n                        new KeyValue(node.scaleXProperty(), 1, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 1, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), 0, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(100),    \n                        new KeyValue(node.scaleXProperty(), 0.9, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 0.9, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), -3, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(200),    \n                        new KeyValue(node.scaleXProperty(), 0.9, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 0.9, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), -3, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(300),    \n                        new KeyValue(node.scaleXProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), 3, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(400),    \n                        new KeyValue(node.scaleXProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), -3, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(500),    \n                        new KeyValue(node.scaleXProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), 3, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(600),    \n                        new KeyValue(node.scaleXProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), -3, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(700),    \n                        new KeyValue(node.scaleXProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), 3, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(800),    \n                        new KeyValue(node.scaleXProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), -3, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(900),    \n                        new KeyValue(node.scaleXProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 1.1, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), 3, WEB_EASE)\n                    ),\n                    new KeyFrame(Duration.millis(1000),    \n                        new KeyValue(node.scaleXProperty(), 1, WEB_EASE),\n                        new KeyValue(node.scaleYProperty(), 1, WEB_EASE),\n                        new KeyValue(node.rotateProperty(), 0, WEB_EASE)\n                    )\n)\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"left\"\u003e\n\u003cpre lang=\"java\"\u003e\n         JFXAnimationTemplate.create()\n             .from()\n             .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n             .percent(10)\n             .percent(20)\n             .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(0.9))\n             .action(b -\u003e b.target(Node::rotateProperty).endValue(-3))\n             .percent(30, 50, 70, 90)\n             .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.1))\n             .action(b -\u003e b.target(Node::rotateProperty).endValue(3))\n             .percent(40, 60, 80)\n             .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.1))\n             .action(b -\u003e b.target(Node::rotateProperty).endValue(-3))\n             .to()\n             .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n             .action(b -\u003e b.target(Node::rotateProperty).endValue(0))\n             .config(b -\u003e b.duration(Duration.seconds(1)).interpolator(WEB_EASE));\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"left\"\u003e\n\u003cpre lang=\"css\"\u003e\n     @keyframes tada {\n       from {\n         transform: scale3d(1, 1, 1);\n       }\n       10%,\n       20% {\n         transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);\n       }\n       30%,\n       50%,\n       70%,\n       90% {\n         transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);\n       }\n       40%,\n       60%,\n       80% {\n         transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);\n       }\n       to {\n         transform: scale3d(1, 1, 1);\n       }\n     }\n\u003c/pre\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n  \n  \n\u003cbr\u003e\n\nAs you can see, the default approach with KeyFrame objects has more lines of code.\u003cbr\u003e\nFurthermore, there is a repetitive number of KeyFrames (each for a specific animation section) which causes a lot of duplicated KeyValue objects.\u003cbr\u003e\u003cbr\u003e\nThe JFXAnimationTemplate approach can handel one specified KeyFrame (action) on more animation sections due to different percentage values.\u003cbr\u003e\nMoreover, you can specify more target observers for one specific end value.\n\n### How To\n\n#### Create a JFXAnimationTemplate\n\nThe created type of JFXTemplate is use case specific. Mostly the JFXTemplateBuilder\nis used as final type, where T is the default animation object type.\u003cbr\u003e\nA JFXTemplate can be created like that:\n\n```java\n...\n      JFXAnimationTemplate.create()\n...\n```\n\nin this case the default animation object type T is a Node type.\u003cbr\u003e\nIt's also possible to set a own default animation object type:\n\n```java\n...\n      JFXAnimationTemplate.create(MyType.class)\n...\n```\n\nAfter the init creation you have to specify a animation interval like you do in CSS.\u003cbr\u003e\nYou can use:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .from()\n...\n```\n\nwhich means 0%,\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .to()\n...\n```\n\nwhich means 100% or\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .percent(10)\n...\n```\n\nwhich is the percentage value. Furthermore you can specify multiple percentage values:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .percent(10)\n          .percent(20)\n          .percent(30)\n...\n```\n\nor via varargs:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .percent(10, 20, 30)\n...\n```\n\nNow you have to implement the specific action or actions like:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .percent(10, 20, 30)\n          .action(...)\n          .action(...)\n...\n```\n\nThe action method can be called by value or in a lazy way. If you use the non lazy method you have to create a JFXAnimationTemplateAction.Builder\u003c?, ?\u003e manually like:\n\n```java\n...\n      JFXAnimationTemplateAction.builder()\n...\n```\n\nThe more comfortable possibility is to use the lazy approach where such a builder is ready to use like:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .percent(10, 20, 30)\n          .action(builder -\u003e builder...)\n...\n```\n\nThe next step is to define the specific animation values like:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .percent(10, 20, 30)\n          .action(b -\u003e b.target(Node::scaleXProperty).endValue(1))\n...\n```\n\nFor example you can use multiple target properties via varargs:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .percent(10, 20, 30)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n...\n```\n\nThere are a lot more functions and also lazy method representations, which also provides access to the actual animation object (like the target method in this example).\u003cbr\u003e\u003cbr\u003e\n\n#### Configure a JFXAnimationTemplate\n\nLets assume we have our animation action defined like this:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .from()\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .percent(14)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(28)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .percent(42)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(70)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n...\n```\n\nWe can finalize the animation by calling the config(...) method after the last action(...) method.\u003cbr\u003e\nAgain there are the same possibilities as for the JFXAnimationTemplateAction.Builder\u003c?, ?\u003e.\u003cbr\u003e\nSo we can use the non lazy version and create a JFXAnimationTemplateConfig.Builder manually like:\n\n```java\n...\n      JFXAnimationTemplateConfig.builder()\n...\n```\n\nor the more comfortable possibility with the lazy approach like:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .from()\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .percent(14)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(28)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .percent(42)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(70)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .config(builder -\u003e builder...);\n\n...\n```\n\nNow we have to define some config values like:\n\n```java\n...\n      JFXAnimationTemplate.create()\n          .from()\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .percent(14)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(28)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .percent(42)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(70)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .config(b -\u003e b.duration(Duration.seconds(1.3)).interpolator(Interpolator.EASE_BOTH));\n\n...\n```\n\nWe have to define the total duration of the animation and we can also define a interpolator which is used by all actions.\u003cbr\u003e\nThere are a lot more functions and also lazy method representations.\u003cbr\u003e\nFor more see the JFXAnimationTemplateConfig class.\u003cbr\u003e\u003cbr\u003e\n\n#### Build a JFXAnimationTemplate\n\nAfter defining the actions and the config method, the last step is to build the final animation.\u003cbr\u003e\nThere are different approaches to build an animation.\u003cbr\u003e\n\n##### Default animation objects\n\nLets assume we have defined our animation for later use like this:\n\n```java\n ...\n  private static final JFXTemplateBuilder\u003cNode\u003e HEART_BEAT =\n      JFXAnimationTemplate.create()\n          .percent(0)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .percent(14)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(28)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .percent(42)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(70)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .config(b -\u003e b.duration(Duration.seconds(1.3)).interpolator(Interpolator.EASE_BOTH));\n\n ...\n```\n\nNow we want e.g. a Button to animate. We would build the animation like:\n\n```java\n  ...\n    Button button = new Button(\"Button\");\n    Timeline timeline = HEART_BEAT.build(button);\n  ...\n```\n\nSo the button is the default animation object and needs to be passed to the build(...) method.\u003cbr\u003e\nThe default return value is the ready to use Timeline.\u003cbr\u003e\nThere is also the possibility to use multiple default animation objects and also named animation objects.\u003cbr\u003e\nFor this purpose we have to use again a Builder in our build(...) method. And again we can do it in a non lazy:\n\n```java\n  ...\n    JFXTemplateBuilder.JFXAnimationObjectMapBuilder.builder()\n  ...\n```\n\nor lazy way:\n\n```java\n  ...\n    Button button = new Button(\"Button\");\n    Timeline timeline = HEART_BEAT.build(builder -\u003e builder...);\n  ...\n```\n\nSo to use multiple default animation objects via varargs we have to do the following:\n\n```java\n  ...\n    Button button = new Button(\"Button\");\n    Button button2 = new Button(\"Button2\");\n  ...\n    Timeline timeline = HEART_BEAT.build(b -\u003e b.defaultObject(button, button2));\n  ...\n```\n\nNow the animation for both buttons are contained in the timeline object.\u003cbr\u003e\n\n##### Named animation objects\n\nLets assume we have defined our animation for later use like this:\n\n```java\n ...\n  private static final JFXTemplateBuilder\u003cNode\u003e HEART_BEAT =\n      JFXAnimationTemplate.create()\n          .percent(0)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .percent(14)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(28)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .action(b -\u003e b.withAnimationObject(\"SpecialNode\").target(Node::translateYProperty).endValue(20))\n          .percent(42)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1.3))\n          .percent(70)\n          .action(b -\u003e b.target(Node::scaleXProperty, Node::scaleYProperty).endValue(1))\n          .config(b -\u003e b.duration(Duration.seconds(1.3)).interpolator(Interpolator.EASE_BOTH));\n\n ...\n```\n\nHere we are using a named animation object \"SpecialNode\".\u003cbr\u003e\nSo this animation object will be used in exactly this action method.\u003cbr\u003e\nThere is also the possibility to define another type for the named animation object like:\n\n```java\n  ...\n          .action(b -\u003e b.withAnimationObject(Button.class, \"SpecialNode\")...)\n  ...\n```\n\nSo a type of Button can be used in the defined animation values.\u003cbr\u003e\nIf we don't define a type a Node type will be used.\u003cbr\u003e\nIt's also possible to define multiple named animation objects via varargs for a specific type:\n\n```java\n  ...\n          .action(b -\u003e b.withAnimationObject(\"SpecialNode\", \"SpecialNode2\", \"SpecialNode3\")...)\n  ...\n```\n\nTo build our animation for e.g. a Button and our special Node we have to do the following:\n\n```java\n  ...\n    Button button = new Button(\"Button\");\n    Label specialNode = new Label(\"Label\");\n\n    Timeline timeline = HEART_BEAT.build(b -\u003e b.defaultObject(button).namedObject(\"SpecialNode\", specialNode));\n  ...\n```\n\nWe can also use multiple named animation objects via varargs for one name like:\n\n```java\n  ...\n    Button button = new Button(\"Button\");\n    Label specialNode = new Label(\"Label\");\n    Label specialNode2 = new Label(\"Label2\");\n\n    Timeline timeline = HEART_BEAT.build(b -\u003e b.defaultObject(button).namedObject(\"SpecialNode\", specialNode, specialNode2));\n  ...\n```\n\n\u003cbr\u003e\u003cbr\u003e\n\n#### Build a specific animation container\n\nThe default animation container for a JFXAnimation is Timeline.\u003cbr\u003e\nIt can explicitly set at build time like:\n\n```java\n  ...\n    Button button = new Button(\"Button\");\n\n    Timeline timeline = myAnimation.build(JFXAnimationTemplates::buildTimeline, button);\n  ...\n```\n\nWhere buildTimeline is just a method which accepts a type of JFXAnimationTemplate, which contains all animation values and configs.\u003cbr\u003e\nTo use another animation container except Timeline, just write your own implementation, which handles the JFXAnimationTemplate instance.\u003cbr\u003e\nFor orientation the implementation of buildTimeline in JFXAnimationTemplates class can be used and copied.\n\n### Since version 2.0.0\n\n#### Action with absolute duration\n\nIt's now also possible to use an action duration like the default behaviour with JavaFX KeyValues:\n\n```java\n ...\n      JFXAnimationTemplate.create()\n          .time(Duration.seconds(3))\n ...\n```\n\nYou can combine time(...) with percent(...) definitions.\n\n#### Dynamic end values and interpolators\n\nThe default behavior of the timeline in JavaFX usually does not allow the end value and/or interpolator to be changed during a running animation.\u003cbr\u003e\nWith a dynamic end value/interpolator this is now possible.\u003cbr\u003e\nTo use e.g. a dynamic end value you could define it like:\n\n```java\n ...\n    JFXAnimationTemplate.create()\n        .percent(10)\n        .action(\n            b -\u003e b.target(Node::rotateProperty).endValue(InterpretationMode.DYNAMIC, node -\u003e 3));\n ...\n```\n\nNow the end value function is called every interpolation step of the action.\u003cbr\u003e\nYou could define your own conditions or other methods in it.\n\nThe same is valid for the interpolator e.g.:\n\n```java\n ...\n    JFXAnimationTemplate.create()\n        .percent(10)\n        .action(\n            b -\u003e\n                b.target(Node::rotateProperty)\n                    .interpolator(InterpretationMode.DYNAMIC, node -\u003e Interpolator.LINEAR));\n ...\n```\n\n#### The more CSS way\n\nIt is now possible to adjust the animation more according to a CSS behavior.\u003cbr\u003e\nFor that purpose the new functions fromToAutoGen and autoReset exist.\u003cbr\u003e\u003cbr\u003e\nThe fromToAutoGen function generates automatically for every action target a related start(from) or end(to) action if it doesn't exist.\u003cbr\u003e\nThe generated actions uses as end values the last target values before the animations is build.\u003cbr\u003e\u003cbr\u003e\nThe autoReset function reset all targets to the values before an animation was built.\u003cbr\u003e\nThe behavior is similar to the animation-fill-mode: backwards in CSS.\u003cbr\u003e\n\nThe functions can be used like:\n\n```java\n ...\n        JFXAnimationTemplate.create()\n            .percent(20)\n            .action(b -\u003e b.target(rectangle.translateXProperty()).endValue(150))\n            .config(b -\u003e b.duration(Duration.seconds(2))\".autoReset()\" or/and \".fromToAutoGen()\")\n            .build();\n ...\n```\n\n![Alt text](https://raw.githubusercontent.com/schlegel11/JFXAnimation/assets/v2_fromTo_reset.gif \"FromTo Reset\")\n\n#### Fluent transition\n\nThe fluent transition function is useful in some situations and can be seen more or less as a helper function.\u003cbr\u003e\nIt can be defined on the whole animation or specific on an action.\u003cbr\u003e\nUseful if an action is interrupted or the animation gets clipped.\u003cbr\u003e\n\nIn this example an action is ignored and the animation would therefore look choppy:\n\n```java\n ...\n        JFXAnimationTemplate.create()\n            .percent(20)\n            .action(b -\u003e b.target(rectangle.translateXProperty()).endValue(150))\n            .percent(60)\n            .action(b -\u003e b.target(rectangle.translateXProperty()).endValue(400).ignore())\n            .config(b -\u003e b.duration(Duration.seconds(2)).fromToAutoGen().fluentTransition())\n            .build();\n ...\n```\n\n![Alt text](https://raw.githubusercontent.com/schlegel11/JFXAnimation/assets/v2_fluentTransition.gif \"Fluent Transition\")\n\n## Demo\n\nA full blown example of animations can be found in the demo project/package.\u003cbr\u003e\nThe demo uses JFoenix and is also included in the JFoenix demo package.\u003cbr\u003e\nIt also requires java 8 or 9.\n\nRun the demo with:\n\n```shell\n ./gradlew demo:animationDemo\n```\n\n![Alt text](https://raw.githubusercontent.com/schlegel11/JFXAnimation/assets/jfx_animation_demo.gif \"Animation Demo\")\n\n## Download\n\nIf you are using JFoenix, you don't have to use this dependency (it's already included in JFoenix).\u003cbr\u003e\nIf you use this dependency and switch later to JFoenix you can remove this dependency.\u003cbr\u003e\nFurthermore, you have to change the package names from _de.schlegel11.jfxanimation.*_ to _com.jfoenix.transitions.template.*_.\n\n### Gradle\n\n```groovy\n compile 'de.schlegel11:jfxanimation:2.0.0'\n```\n\n### Maven\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ede.schlegel11\u003c/groupId\u003e\n  \u003cartifactId\u003ejfxanimation\u003c/artifactId\u003e\n  \u003cversion\u003e2.0.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschlegel11%2FJFXAnimation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschlegel11%2FJFXAnimation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschlegel11%2FJFXAnimation/lists"}