Skip to content

Commit

Permalink
Allow bounce easings along a path to return a position outside of the…
Browse files Browse the repository at this point in the history
… path (#2457)

Don't clamp interpolated distance along path to 'progress' value between 0 and 1.

Bounce in / Bounce out easings can transform the progress to negative values or values higher than 1. `getPosTan` unfortunately clamps the input to be between 0 and 1, so we need to handle the t < 0 and t > 1 cases separately.


This is for the same issue I helped fix in the flutter library as well here: xvrh/lottie-flutter#330

Expected result (both bounce-in and bounce out) along linear and curved paths: 

https://github.com/airbnb/lottie-android/assets/632735/6a25e139-fc81-4c3b-b3f3-be118c56db06
  • Loading branch information
idlewan committed Jan 31, 2024
1 parent 8b8c22b commit a9d3a16
Show file tree
Hide file tree
Showing 2 changed files with 916 additions and 2 deletions.
Expand Up @@ -11,6 +11,7 @@
public class PathKeyframeAnimation extends KeyframeAnimation<PointF> {
private final PointF point = new PointF();
private final float[] pos = new float[2];
private final float[] tangent = new float[2];
private final PathMeasure pathMeasure = new PathMeasure();
private PathKeyframe pathMeasureKeyframe;

Expand Down Expand Up @@ -39,8 +40,23 @@ pathKeyframe.startValue, pathKeyframe.endValue, getLinearCurrentKeyframeProgress
pathMeasureKeyframe = pathKeyframe;
}

pathMeasure.getPosTan(keyframeProgress * pathMeasure.getLength(), pos, null);
point.set(pos[0], pos[1]);
// allow bounce easings to calculate positions outside the path
// by using the tangent at the extremities

float length = pathMeasure.getLength();

if (keyframeProgress < 0) {
pathMeasure.getPosTan(0, pos, tangent);
float tangentAmount = keyframeProgress * length;
point.set(pos[0] + tangent[0] * tangentAmount, pos[1] + tangent[1] * tangentAmount);
} else if (keyframeProgress > 1) {
pathMeasure.getPosTan(length, pos, tangent);
float tangentAmount = (keyframeProgress - 1) * length;
point.set(pos[0] + tangent[0] * tangentAmount, pos[1] + tangent[1] * tangentAmount);
} else {
pathMeasure.getPosTan(keyframeProgress * length, pos, null);
point.set(pos[0], pos[1]);
}
return point;
}
}

0 comments on commit a9d3a16

Please sign in to comment.