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;
}
/**
* 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.
*/

View File

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

View File

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

View File

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

View File

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

View File

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