JavaFx 2.0 – Presenter

Hi,

As I mentioned in previous post I spend some time to try JavaFx 2.0 beta release. After playing a little with the tutorials, I try myself writing code that would include JavaFx Node transition, effects and coordinates manipulation.

I tried writing a simple slide presenter where slide would be defined in the graphic system coordinate as javafx.scene.Group and could be added to a com.mrlonee.presenter.Presenter. A little video of the sample presenter application is available :

[local /wp-content/uploads/2011/06/presenter.avi Presenter]

Here is a snapshot of the global view proposed by the application when it is launched

Initial overview is performed by scaling down the root node.

//Initial Scale
slideRoot.scaleXProperty().set(0.2);
slideRoot.scaleYProperty().set(0.2);

This presenter is responsible for proposing a container Group and a simple method to present next or previous element.

public interface Presenter{
 
public void addElementToPresent(final Node node);
 
public void presentNextElement();
 
public void presentPreviousElement();
 
public void presentElement(final Node node);
 
public Group getRootNode();
}

Slide declaration is for now done by constructing Nodes. Here is an example of what I’ve done for my sample application :

/*
* Hello slide
*/
Distant lightEffectDistant = new Light.Distant();
lightEffectDistant.azimuthProperty().set(-135);
 
Text text = new TextBuilder()
.content("Hello").x(0).y(300).fill(Color.GREEN).font(new Font(50))
.effect(new LightingBuilder().light(lightEffectDistant).surfaceScale(5.0).build())
.build();
 
presenterServices.addElementToPresent(text);
 
/*
* Slide 1
*/
List slide1Stops = new ArrayList();
slide1Stops.add(new StopBuilder().offset(0.0).color(Color.BLUE).build());
slide1Stops.add(new StopBuilder().offset(1.0).color(Color.DARKBLUE).build());
 
Group slide1 = new GroupBuilder().children(
new RectangleBuilder()
.x(0).y(0).width(200).height(150)
.fill(new LinearGradientBuilder().startX(0.5).startY(0.0).endX(1.0).endY(0.0)
.stops(slide1Stops).proportional(true).cycleMethod(CycleMethod.REPEAT).build())
.build(),
 
new TextBuilder().x(60).y(70).font(new Font(30))
.textAlignment(TextAlignment.CENTER).content("JavaFx")
.smooth(true).fill(Color.WHITE)
.effect(new DropShadowBuilder().offsetX(3.0).offsetY(3.0).build()).build(),
 
new TextBuilder().x(75).y(90).font(new Font(20))
.textAlignment(TextAlignment.CENTER).content("Rocks")
.smooth(true).fill(Color.WHITE).build()
).translateX(-200).translateY(-300).build();
 
presenterServices.addElementToPresent(slide1);
 
/*
* Slide 2
*/
List slide2Stops = new ArrayList();
slide2Stops.add(new StopBuilder().offset(0.2).color(Color.RED).build());
slide2Stops.add(new StopBuilder().offset(0.8).color(Color.RED.darker()).build());
slide2Stops.add(new StopBuilder().offset(1.0).color(Color.RED).build());
 
Group slide2 = new GroupBuilder().children(
new CircleBuilder()
.centerX(200).centerY(200).radius(200)
.fill(new RadialGradientBuilder().centerX(0.3).centerY(0.3).stops(slide2Stops).build())
.build(),
 
new TextBuilder().x(115).y(180).font(new Font(30))
.textAlignment(TextAlignment.CENTER).content("MrLoNee Too !")
.effect(new ReflectionBuilder().fraction(0.8).build())
.smooth(true).fill(Color.WHITE).build()
).translateX(400).translateY(400).build();
 
presenterServices.addElementToPresent(slide2);

Transition between each element is composed of a translate and and scale transition played together. It gives the effect that we scale up and down while translating to the next slide to present as follow

The translation code is above :

Timeline animationTransition = new TimelineBuilder()
.keyFrames(
new KeyFrame(Duration.ZERO,
new KeyValue( this.root.translateXProperty(), fromX),
new KeyValue( this.root.translateYProperty(), fromY)
),
new KeyFrame(Duration.ZERO,
new KeyValue( this.root.scaleXProperty(), this.root.scaleXProperty().get()),
new KeyValue( this.root.scaleYProperty(), this.root.scaleYProperty().get())
),
new KeyFrame(Duration.valueOf(300),
new KeyValue( this.root.scaleXProperty(), 0.7),
new KeyValue( this.root.scaleYProperty(), 0.7)
),
new KeyFrame(Duration.valueOf(150),
new KeyValue( this.root.translateXProperty(), fromX + (toX - fromX)/6),
new KeyValue( this.root.translateYProperty(), fromY + (toY - fromY)/6)
),
new KeyFrame(Duration.valueOf(450),
new KeyValue( this.root.translateXProperty(), fromX + (toX - fromX)*5/6),
new KeyValue( this.root.translateYProperty(), fromY + (toY - fromY)*5/6)
),
new KeyFrame(Duration.valueOf(600),
new KeyValue(this.root.translateXProperty(), toX),
new KeyValue(this.root.translateYProperty(), toY)
),
new KeyFrame(Duration.valueOf(600),
new KeyValue( this.root.scaleXProperty(), finalScale),
new KeyValue( this.root.scaleYProperty(), finalScale)
)
)
.build();

A Thumb view is built by the presenter as you add element to present. This thumb view just add a cyan circle node that is surrounded by a blue circle as the slide with thumb circle index  is presented. An example for third slide would be :

The source code is available in presenter.jar file in download page !

Feel free to try it. I might upgrade it with :

  • scale each slide so that it take the whole frame size
  • propose real node thumb to navigate when there is many slide
  • propose a way to choose what animation transition shall be taken
  • propose a slide editor (well it may be long I suppose…)

I still have to find a way to perform a scale animation that is using a custom scale center. I could use it to finish to scale so that the currently presented slide takes the whole frame width/height instead of using 1.0 scale of the slide.

LoNee

3 comments

Leave a Reply

Your email address will not be published. Required fields are marked *