Friday, February 26, 2016

FridayFun XXIII

Finally Friday again...
I just recognized that it's more than a year ago that I posted a Friday Fun Component...so here you go...

Last Monday I was skimming the web for interesting controls and stumbled upon the following image.



This might be a very handy gauge for some visualizations like health dashboards etc. In principle it would be very easy to realize something like this because it just contains a few visual parts.
The interesting part of that control is the wavy shaped top edge of the inner fill. If you would like to keep it static this is also no big deal BUT...would it not be cooler if the surface will be animated???
I found some code on the web that did something similar and ported it to Java.

Long story short, here is a little video of the control in action...



I've added the code to the medusa demo project that you can find on github (it is called FunLevelGauge).
Instead of using a special Skin for the Medusa Gauge I've simply took a Region and added a Medusa Gauge as member variable.
The code for the Gauge is very simple and looks like this...

Gauge gauge = GaugeBuilder.create()
                          .minValue(0)
                          .maxValue(1)
                          .animated(true)
                          .build();
As you can see this is really nothing special. For the visualization I used a JavaFX Canvas node that I clipped with a simple JavaFX Circle element.
The ring around the control is again a JavaFX Circle that has a transparent fill and a stroke with the same color as the inner part.
The JavaFX Text node in the center of the control changes it's color dependent on the fill level of the control. The color for the text will be derived from the fill color.
If you would like to play around with the waviness of the surface you might want to play around with the following parameters...
  • detail        (no of points used for the wave)
  • friction            
  • density 
In the example I add an impulse to the wave every second to keep the wave moving but you could also think about to add an impulse only when a new level was set like this...
public void setLevel(final double LEVEL) {
    gauge.setValue(LEVEL);
    Point p;
    for( int i = 0 ; i < detail + 1 ; i++ ) {
        p = particles.get(i);
        p.y = size * (1d - LEVEL);
        p.originalY = p.y;
    }
    text.setText(String.format(Locale.US, "%.0f%%", 100 * LEVEL));
    text.setX((size - text.getLayoutBounds().getWidth()) * 0.5);
    text.setFill(LEVEL < 0.45 ? darkerColor : brighterColor);
    impulse();
}
Therefore you just have to add the call the impulse() method to the setLevel() method and remove the following code from the AnimationTimer
if (now > lastImpulseCall + impulseInterval) {
    impulse();
    lastImpulseCall = now;
}


Please keep in mind that this is (like the name says) a Fun Component and that there is always room for improvements but it's good enough to give you some ideas...

And that's it for today, enjoy the upcoming weekend and keep coding...

1 comment: