2017-07-21 1 views
4

Après avoir lu la documentation, je suis encore un peu confus sur la façon d'exécuter une animation après une autre a terminé. J'ai un calendrier comme ceci:Animation consécutive dans TornadoFX?

timeline { 
    keyframe(Duration.seconds(0.5)) { 
    keyvalue(firstImg.scaleXProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) 
    keyvalue(firstImg.scaleYProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) 
    keyvalue(firstImg.rotateProperty(), 0.0, interpolator = Interpolator.EASE_BOTH) 
    } 

    keyframe(Duration.seconds(0.5)) { 
    keyvalue(secondImg.scaleXProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) 
    keyvalue(secondImg.scaleYProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) 
    keyvalue(secondImg.rotateProperty(), 0.0, interpolator = Interpolator.EASE_BOTH) 
    } 

    keyframe(Duration.seconds(0.5)) { 
    keyvalue(thirdImg.scaleXProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) 
    keyvalue(thirdImg.scaleYProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) 
    keyvalue(thirdImg.rotateProperty(), 0.0, interpolator = Interpolator.EASE_BOTH) 
    } 

    keyframe(Duration.seconds(0.5)) { 
    keyvalue(fourthImg.scaleXProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) 
    keyvalue(fourthImg.scaleYProperty(), 1.0, interpolator = Interpolator.EASE_BOTH) 
    keyvalue(fourthImg.rotateProperty(), 0.0, interpolator = Interpolator.EASE_BOTH) 
    } 
} 

Cela leur va tout à la fois, mais je voudrais courir après chaque animation l'autre a fini! Je ne peux pas tout à fait à comprendre comment faire .. (désolé si cela est évident, je suis très nouveau pour Kotlin et Java en général!)

Je vois que l'image-clé a une propriété onFinished mais je peux pas tout à fait comprendre ce que je suis censé réellement mis à. Y a-t-il une meilleure manière de faire cela? Je vous remercie!

Répondre

3

Il existe une classe "SequentialTransition" JavaFX qui exécutera vos timelines en séquence. Vous devez désactiver la lecture automatique TornadoFX avec un indicateur transmis dans le générateur de montage. Découvrez ParallelTransition si vous voulez les exécuter tous en même temps en utilisant un modèle de codage similaire.

class STTest : View("My View") { 

    val r1 = Rectangle(20.0, 20.0, Color.RED) 
    val r2 = Rectangle(20.0, 20.0, Color.YELLOW) 
    val r3 = Rectangle(20.0, 20.0, Color.GREEN) 
    val r4 = Rectangle(20.0, 20.0, Color.BLUE) 

    override val root = vbox { 

     button("Animate") { 
      setOnAction { 

       val t1 = timeline(false) { 
        keyframe(Duration.seconds(0.5)) { 
         keyvalue(r1.translateXProperty(), 50.0, interpolator = Interpolator.EASE_BOTH) 
        } 
       } 
       val t2 = timeline(false) { 
        keyframe(Duration.seconds(0.5)) { 
         keyvalue(r2.translateXProperty(), 100.0, interpolator = Interpolator.EASE_BOTH) 
        } 
       } 
       val t3 = timeline(false) { 
        keyframe(Duration.seconds(0.5)) { 
         keyvalue(r3.translateXProperty(), 150.0, interpolator = Interpolator.EASE_BOTH) 
        } 
       } 
       val t4 = timeline(false) { 
        keyframe(Duration.seconds(0.5)) { 
         keyvalue(r4.translateXProperty(), 200.0, interpolator = Interpolator.EASE_BOTH) 
        } 
       } 

       /* functions look better 
       val st = SequentialTransition() 
       st.children += t1 
       st.children += t2 
       st.children += t3 
       st.children += t4 

       st.play() 
       */ 

       t1.then(t2).then(t3).then(t4).play() 

      } 
     } 
     pane { 
      add(r1) 
      add(r2) 
      add(r3) 
      add(r4) 
     } 
    } 

} 
+0

travaillé comme un charme, merci! J'aime le format d'utilisation .then, très lisible et facile à comprendre pour un noob comme moi lol – shanling

3

Sur la base de la structure proposée par @ tornadofx-fan que j'ai ajouté les constructeurs pour sequentialTransition et parallelTransition, à partir de si vous TornadoFX 1.7.9 pouvez faire la même chose comme ceci:

class TransitionViews: View() { 
    val r1 = Rectangle(20.0, 20.0, Color.RED) 
    val r2 = Rectangle(20.0, 20.0, Color.YELLOW) 
    val r3 = Rectangle(20.0, 20.0, Color.GREEN) 
    val r4 = Rectangle(20.0, 20.0, Color.BLUE) 

    override val root = vbox { 
     button("Animate").action { 
      sequentialTransition { 
       timeline { 
        keyframe(0.5.seconds) { 
         keyvalue(r1.translateXProperty(), 50.0, interpolator = Interpolator.EASE_BOTH) 
        } 
       } 
       timeline { 
        keyframe(0.5.seconds) { 
         keyvalue(r2.translateXProperty(), 100.0, interpolator = Interpolator.EASE_BOTH) 
        } 
       } 
       timeline { 
        keyframe(0.5.seconds) { 
         keyvalue(r3.translateXProperty(), 150.0, interpolator = Interpolator.EASE_BOTH) 
        } 
       } 
       timeline { 
        keyframe(0.5.seconds) { 
         keyvalue(r4.translateXProperty(), 200.0, interpolator = Interpolator.EASE_BOTH) 
        } 
       } 
      } 
     } 
     pane { 
      add(r1) 
      add(r2) 
      add(r3) 
      add(r4) 
     } 
    } 
} 

Le Le générateur de chronologie à l'intérieur de ces transitions ne joue pas automatiquement, tandis que la transition elle-même est jouée automatiquement à la fin du générateur. Vous pouvez transmettre play=false au générateur de transition pour désactiver la lecture automatique.

Notez également l'utilisation de 0.5.seconds pour générer les objets :) Durée

+0

génial, excité pour 1.7.9! : ^) – shanling

1

Dans ce cas où vous configurez simplement des échelles et des rotations, il y a quelques aides agréables déjà dans la bibliothèque. Cela devrait fonctionner pour vous:

val time = 0.5.seconds 
firstImg.scale(time, Point2D(1.0, 1.0), play = false).and(firstImg.rotate(time, 0.0, play = false)) 
     .then(secondImg.scale(time, Point2D(1.0, 1.0), play = false).and(secondImg.rotate(time, 0.0, play = false))) 
     .then(thirdImg.scale(time, Point2D(1.0, 1.0), play = false).and(thirdImg.rotate(time, 0.0, play = false))) 
     .then(fourthImg.scale(time, Point2D(1.0, 1.0), play = false).and(fourthImg.rotate(time, 0.0, play = false))) 
     .play() 

Le play = false partout est nécessaire puisque ces aides ont été conçus pour de simples animations ponctuelles-jeu automatique.

Modifier

Après a discussion in Slack, ceux-ci peuvent être simplifié dans une version future, de sorte que le ci-dessus peut éventuellement être aussi facile que

val time = 0.5.seconds 
listOf(
    firstImg.scale(time, 1 p 1) and firstImg.rotate(time, 0), 
    secondImg.scale(time, 1 p 1) and secondImg.rotate(time, 0), 
    thirdImg.scale(time, 1 p 1) and thirdImg.rotate(time, 0), 
    fourthImg.scale(time, 1 p 1) and fourthImg.rotate(time, 0) 
).playSequential() 

Regardez les notes de version pour plus d'informations!

Autre Modifier

On dirait que je suis sur ce qui complique les choses un peu. Vous pouvez simplement l'utiliser si vous l'aimez plus:

val time = 0.5.seconds 
SequentialTransition(
    firstImg.scale(time, Point2D(1.0, 1.0), play = false).and(firstImg.rotate(time, 0.0, play = false)). 
    secondImg.scale(time, Point2D(1.0, 1.0), play = false).and(secondImg.rotate(time, 0.0, play = false)), 
    thirdImg.scale(time, Point2D(1.0, 1.0), play = false).and(thirdImg.rotate(time, 0.0, play = false)), 
    fourthImg.scale(time, Point2D(1.0, 1.0), play = false).and(fourthImg.rotate(time, 0.0, play = false)) 
).play()