Created
July 20, 2017 12:42
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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