Skip to content

Instantly share code, notes, and snippets.

@piyushgupta27
Created July 20, 2017 12:42
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save piyushgupta27/2f1fa9e6f13bfdf38d00ee7e90018570 to your computer and use it in GitHub Desktop.
Save piyushgupta27/2f1fa9e6f13bfdf38d00ee7e90018570 to your computer and use it in GitHub Desktop.
A util tool for smooth animation of a Google map marker from a startLocation to an endLocation
/**
* Method to animate marker to destination location
* @param destination destination location (must contain bearing attribute, to ensure
* marker rotation will work correctly)
* @param marker marker to be animated
*/
public static void animateMarker(Location destination, Marker marker) {
if (marker != null) {
LatLng startPosition = marker.getPosition();
LatLng endPosition = new LatLng(destination.getLatitude(), destination.getLongitude());
float startRotation = marker.getRotation();
LatLngInterpolator latLngInterpolator = new LatLngInterpolator.LinearFixed();
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(1000); // duration 1 second
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override public void onAnimationUpdate(ValueAnimator animation) {
try {
float v = animation.getAnimatedFraction();
LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, endPosition);
marker.setPosition(newPosition);
marker.setRotation(computeRotation(v, startRotation, destination.getBearing()));
} catch (Exception ex) {
// I don't care atm..
}
}
});
valueAnimator.start();
}
}
/**
* Method to compute rotation (or marker's bearing) for specified fraction of animation.
* Marker is rotated in the direction which is closer from start to end.
*
* @param fraction Fraction of animation completed b/w start and end location
* @param start Rotation (or Bearing) for animation's start location
* @param end Rotation (or Bearing) for animation's end location
**/
private static float computeRotation(float fraction, float start, float end) {
float normalizeEnd = end - start; // rotate start to 0
float normalizedEndAbs = (normalizeEnd + 360) % 360;
float direction = (normalizedEndAbs > 180) ? -1 : 1; // -1 = anticlockwise, 1 = clockwise
float rotation;
if (direction > 0) {
rotation = normalizedEndAbs;
} else {
rotation = normalizedEndAbs - 360;
}
float result = fraction * rotation + start;
return (result + 360) % 360;
}
private interface LatLngInterpolator {
LatLng interpolate(float fraction, LatLng a, LatLng b);
class LinearFixed implements LatLngInterpolator {
@Override
public LatLng interpolate(float fraction, LatLng a, LatLng b) {
double lat = (b.latitude - a.latitude) * fraction + a.latitude;
double lngDelta = b.longitude - a.longitude;
// Take the shortest path across the 180th meridian.
if (Math.abs(lngDelta) > 180) {
lngDelta -= Math.signum(lngDelta) * 360;
}
double lng = lngDelta * fraction + a.longitude;
return new LatLng(lat, lng);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment