A few people at work have Nohohon Zoku solar powered bobble heads. I like watching them bob their heads all day, so I thought it'd be fun to make a virtual bobble head. In this post, I'll show you how to create your very own bobble head using the JavaFX Production Suite tools and a simple JavaFX script to tie everything together. If you'd like, you can download the source code from GitHub and play with it or follow along and create your own new project.

To achieve this effect, we can use JavaFX’s PathTransition with an indefinite repeat count. Path transitions allow us to define a rail on which a node can slide across. In our image, we just need to name two nodes specially: one for the head and one to represent the track on which the head will “bobble.” Here’s a diagram of what the two nodes look like:

Diagram of Smiley Nodes

Here is the actual SVG source file I’m using for this example. In our animation, we want the head node to simply travel back and forth along the rotatePath as illustrated above. Once we’ve drawn our illustration using an SVG editor (I’m using InkScape), we need to convert it a JavaFX-ready asset by using Production Suite’s SVG Converter that we can import into our project.

Below is a picture of what our final animation will look like. Click on the image if you want to see it in action (NOTE: the page may require you to install JavaFX runtime libraries).

The Full Smiley Scene

Production Suite UI Stub: SmileyUI.fx

To use the FXZ file that we generate using SVG Convter, first make sure your project references the javafx-fxd-runtime library. We can then generate our stub by right clicking on the FXZ file and choosing Generate UI Stub… The UI Stub Generator will add to our stub among other fields, the head and rotatePath nodes. Below is a snippet of the automatically generated stub. I removed the extraneous nodes that the UI Stub generated also added.

  package net.newfoo.smiley;
  
  import java.lang.Object;
  import java.lang.System;
  import java.lang.RuntimeException;
  import javafx.scene.Node;
  import javafx.fxd.UiStub;
  
  public class SmileyUI extends UiStub {
  	
  	override public var url = "{__DIR__}Smiley.fxz";
  	
  	public var head: Node;
  	public var rotatePath: Node;
  	
  	override protected function update() {
  		lastNodeId = null;
		 try {
			head=getNode("head");
			rotatePath=getNode("rotatePath");
		} catch( e:java.lang.Exception) {
			System.err.println("Update of the  attribute '{lastNodeId}' failed with: {e}");
			throw e;
		}
	}
  }

Main Script

Tying it together is fairly straightward. We just need to create an instance of our UI stub and then setup an appropriate PathTransition. For the path property of the transition, you’ll notice that we’re just using rotatePath from our FXZ asset. The orientation was set to _ORTHOGONAL_TO_TANGENT_ so that head would rotate slightly as it travels along the rail. Here’s the pertinent code to do that:

  var scene = SmileyUI{ };
  var node = scene.head;
  var path = scene.rotatePath as SVGPath;
    
  var pathTransition = PathTransition {
        duration: 4s node: scene.head
        path: AnimationPath.createFromPath(scene.rotatePath)
        orientation: OrientationType.ORTHOGONAL_TO_TANGENT
        repeatCount: Timeline.INDEFINITE, autoReverse: true
        interpolate: Interpolator.EASEBOTH
  }
  pathTransition.play();
  

The Production Suite Potential

Once the scene was drawn with InkScape, this example really only saved us some small time in creating this particular animation. This example hints at the raw potential of the Production Suite for producing much larger projects however. This technique would allow a non-programmer to define the behavior. You can also use the same techniques in more complicated scenarios. For instance, you could control the paths of sprites in a video game. You could use this technique to control the the transition between one screen to another in an application.

comments powered by Disqus