AnimatedPainter: support individual animation duration, resolution and interpolator depending on value(s)

This commit is contained in:
Karl Tauber
2021-11-22 22:07:45 +01:00
parent 3b489e8e1a
commit 26d7008c04
6 changed files with 57 additions and 13 deletions

View File

@@ -132,6 +132,32 @@ public interface AnimatedPainter
return CubicBezierEasing.STANDARD_EASING; return CubicBezierEasing.STANDARD_EASING;
} }
/**
* Returns the duration of the animation in milliseconds (default is 150)
* for the given value index and value.
*/
default int getAnimationDuration( int valueIndex, float value ) {
return getAnimationDuration();
}
/**
* Returns the resolution of the animation in milliseconds (default is 10)
* for the given value index and value.
* Resolution is the amount of time between timing events.
*/
default int getAnimationResolution( int valueIndex, float value ) {
return getAnimationResolution();
}
/**
* Returns the interpolator for the animation
* for the given value index and value.
* Default is {@link CubicBezierEasing#STANDARD_EASING}.
*/
default Interpolator getAnimationInterpolator( int valueIndex, float value ) {
return getAnimationInterpolator();
}
/** /**
* Returns the client property key used to store the animation support. * Returns the client property key used to store the animation support.
*/ */

View File

@@ -29,6 +29,7 @@ import javax.swing.JComponent;
*/ */
class AnimatedPainterSupport class AnimatedPainterSupport
{ {
private int valueIndex;
private float startValue; private float startValue;
private float targetValue; private float targetValue;
private float animatedValue; private float animatedValue;
@@ -76,8 +77,6 @@ class AnimatedPainterSupport
jc.putClientProperty( key, ass ); jc.putClientProperty( key, ass );
} }
float[] animatedValues = new float[ass.length];
for( int i = 0; i < ass.length; i++ ) { for( int i = 0; i < ass.length; i++ ) {
AnimatedPainterSupport as = ass[i]; AnimatedPainterSupport as = ass[i];
float value = values[i]; float value = values[i];
@@ -85,15 +84,29 @@ class AnimatedPainterSupport
if( as == null ) { if( as == null ) {
// painted first time --> do not animate, but remember current component value // painted first time --> do not animate, but remember current component value
as = new AnimatedPainterSupport(); as = new AnimatedPainterSupport();
as.valueIndex = i;
as.startValue = as.targetValue = as.animatedValue = value; as.startValue = as.targetValue = as.animatedValue = value;
ass[i] = as; ass[i] = as;
} else if( value != as.targetValue ) { } else if( value != as.targetValue ) {
// value changed --> (re)start animation // value changed --> (re)start animation
int animationDuration = painter.getAnimationDuration( as.valueIndex, value );
// do not animate if animation duration (for current value) is zero
if( animationDuration <= 0 ) {
if( as.animator != null ) {
as.animator.cancel();
as.animator = null;
}
as.startValue = as.targetValue = as.animatedValue = value;
as.fraction = 0;
continue;
}
if( as.animator == null ) { if( as.animator == null ) {
// create animator // create animator
AnimatedPainterSupport as2 = as; AnimatedPainterSupport as2 = as;
as.animator = new Animator( painter.getAnimationDuration(), fraction -> { as.animator = new Animator( 1, fraction -> {
// check whether component was removed while animation is running // check whether component was removed while animation is running
if( !c.isDisplayable() ) { if( !c.isDisplayable() ) {
as2.animator.stop(); as2.animator.stop();
@@ -116,19 +129,22 @@ class AnimatedPainterSupport
// if animation is still running, restart it from the current // if animation is still running, restart it from the current
// animated value to the new target value with reduced duration // animated value to the new target value with reduced duration
as.animator.cancel(); as.animator.cancel();
int duration2 = (int) (painter.getAnimationDuration() * as.fraction); int duration2 = (int) (animationDuration * as.fraction);
if( duration2 > 0 ) if( duration2 > 0 )
as.animator.setDuration( duration2 ); as.animator.setDuration( duration2 );
as.startValue = as.animatedValue; as.startValue = as.animatedValue;
} else { } else {
// new animation // new animation
as.animator.setDuration( painter.getAnimationDuration() ); as.animator.setDuration( animationDuration );
as.animator.setResolution( painter.getAnimationResolution() );
as.animator.setInterpolator( painter.getAnimationInterpolator() );
as.animatedValue = as.startValue; as.animatedValue = as.startValue;
} }
// update animator for new value
as.animator.setResolution( painter.getAnimationResolution( as.valueIndex, value ) );
as.animator.setInterpolator( painter.getAnimationInterpolator( as.valueIndex, value ) );
// start animation
as.targetValue = value; as.targetValue = value;
as.animator.start(); as.animator.start();
} }
@@ -137,10 +153,12 @@ class AnimatedPainterSupport
as.y = y; as.y = y;
as.width = width; as.width = width;
as.height = height; as.height = height;
animatedValues[i] = as.animatedValue;
} }
float[] animatedValues = new float[ass.length];
for( int i = 0; i < ass.length; i++ )
animatedValues[i] = ass[i].animatedValue;
painter.paintAnimated( c, (Graphics2D) g, x, y, width, height, animatedValues ); painter.paintAnimated( c, (Graphics2D) g, x, y, width, height, animatedValues );
} }

View File

@@ -171,7 +171,7 @@ public class FlatAnimatedBorderTest
add(durationLabel, "cell 0 11"); add(durationLabel, "cell 0 11");
//---- durationField ---- //---- durationField ----
durationField.setModel(new SpinnerNumberModel(200, 100, null, 50)); durationField.setModel(new SpinnerNumberModel(200, 0, null, 50));
add(durationField, "cell 0 11"); add(durationField, "cell 0 11");
// JFormDesigner - End of component initialization //GEN-END:initComponents // JFormDesigner - End of component initialization //GEN-END:initComponents
} }

View File

@@ -113,7 +113,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JSpinner" ) { add( new FormComponent( "javax.swing.JSpinner" ) {
name: "durationField" name: "durationField"
"model": new javax.swing.SpinnerNumberModel { "model": new javax.swing.SpinnerNumberModel {
minimum: 100 minimum: 0
stepSize: 50 stepSize: 50
value: 200 value: 200
} }

View File

@@ -145,7 +145,7 @@ public class FlatAnimatedIconTest
add(durationLabel, "cell 0 7 3 1"); add(durationLabel, "cell 0 7 3 1");
//---- durationField ---- //---- durationField ----
durationField.setModel(new SpinnerNumberModel(200, 100, null, 50)); durationField.setModel(new SpinnerNumberModel(200, 0, null, 50));
add(durationField, "cell 0 7 3 1"); add(durationField, "cell 0 7 3 1");
//---- buttonGroup1 ---- //---- buttonGroup1 ----

View File

@@ -88,7 +88,7 @@ new FormModel {
add( new FormComponent( "javax.swing.JSpinner" ) { add( new FormComponent( "javax.swing.JSpinner" ) {
name: "durationField" name: "durationField"
"model": new javax.swing.SpinnerNumberModel { "model": new javax.swing.SpinnerNumberModel {
minimum: 100 minimum: 0
stepSize: 50 stepSize: 50
value: 200 value: 200
} }