android - google.maps.animation.drop delay with




Animating markers on Google Maps v2 (3)

What is the best way to animate markers on Google Maps using v2 API?

I am working on a map-centered game where I track locations of people and display them on the map for each other to see. As people move, I want to animate a marker from his current to his latest position. Every person has a direction, so I need to rotate the marker appropriately.

What is the best way to do it using the new Google Maps API?

https://code.i-harness.com


Usage Example for DiscDev's ansrwer (Above):

LatLng fromLocation = new LatLng(38.5, -100.4); // Whatever origin coordinates
LatLng toLocation = new LatLng(37.7, -107.7); // Whatever destination coordinates
Marker marker = mMap.addMarker(new MarkerOptions().position(firstLocation));
MarkerAnimation.animateMarkerToICS(marker, toLocation, new LatLngInterpolator.Spherical());

And for those of you who uses GPS / or any position provider that receives location updates:

Marker ourGlobalMarker;
// We've got a location from some provider of ours, now we can call:
private void updateMarkerPosition(Location newLocation) {

    LatLng newLatLng = new LatLng(newLocation.getLatitude(), newLocation.getLongitude());

    if(ourGlobalMarker == null) { // First time adding marker to map
        ourGlobalMarker = mMap.addMarker(new MarkerOptions().position(newLatLng));
    }
    else {
        MarkerAnimation.animateMarkerToICS(ourGlobalMarker, newLatLng, new LatLngInterpolator.Spherical());
    }         
}

IMPORTANT:

Within 1MarkerAnimation.java If the animation duration is set to X, and your are receiving location updates in a rate smaller then X, multiple animations will run, and you might see the marker flickers.

To avoid this, the animationMarkerToICS method (I took here animationMarkerToICS for example), should look something like this,

full method implementation:

private static Animator animator; // MAKING ANIMATOR GLOBAL INSTEAD OF LOCAL TO THE STATIC FUNCTION

...

// Ice Cream Sandwich compatible
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public static void animateMarkerToICS(Marker marker, LatLng finalPosition, final LatLngInterpolator latLngInterpolator) {

    TypeEvaluator<LatLng> typeEvaluator = new TypeEvaluator<LatLng>() {
        @Override
        public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
            return latLngInterpolator.interpolate(fraction, startValue, endValue);
        }
    };
    Property<Marker, LatLng> property = Property.of(Marker.class, LatLng.class, "position");

    // ADD THIS TO STOP ANIMATION IF ALREADY ANIMATING TO AN OBSOLETE LOCATION
    if(animator != null && animator.isRunning()) {
        animator.cancel();
        animator = null;
    }
    animator = ObjectAnimator.ofObject(marker, property, typeEvaluator, finalPosition);
    animator.setDuration((long) ANIMATION_DURATION);
    animator.start();
}

Enjoy.


Marker has a new function added as of rev.7 of API v2. Marker.setIcon, so you can use multiple icons to show direction.


    //Your code         
    double bearing = 0.0;
             bearing = getBearing(new LatLng(
                                                currentPosition.latitude
                                                ,currentPosition.longitude),
                                        new LatLng(
                                                nextPosition.latitude,
                                                nextPosition.longitude));  

          bearing -= 90;
                            CameraPosition cameraPosition = new CameraPosition
                                    .Builder()
                                    .target(new LatLng(nextPosition.latitude, nextPosition.longitude))
                                    .bearing((float) bearing)
                                    .zoom(ZOOM_LEVEL).build();


                            mGoogleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 5000, null);

                 animatedMarker(currentPosition,nextPosition,busMarker);



                //Method for finding bearing between two points
                    private float getBearing(LatLng begin, LatLng end) {
                        double lat = Math.abs(begin.latitude - end.latitude);
                        double lng = Math.abs(begin.longitude - end.longitude);
                        if (begin.latitude < end.latitude && begin.longitude < end.longitude)
                            return (float) (Math.toDegrees(Math.atan(lng / lat)));
                        else if (begin.latitude >= end.latitude && begin.longitude < end.longitude)
                            return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 90);
                        else if (begin.latitude >= end.latitude && begin.longitude >= end.longitude)
                            return (float) (Math.toDegrees(Math.atan(lng / lat)) + 180);
                        else if (begin.latitude < end.latitude && begin.longitude >= end.longitude)
                            return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 270);
                        return -1;
                    }

   private void animatedMarker(final LatLng startPosition,final LatLng nextPosition,final Marker mMarker)
    {

        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        final Interpolator interpolator = new AccelerateDecelerateInterpolator();
        final float durationInMs = 3000;
        final boolean hideMarker = false;

        handler.post(new Runnable() {
            long elapsed;
            float t;
            float v;

            @Override
            public void run() {
                // Calculate progress using interpolator
                elapsed = SystemClock.uptimeMillis() - start;
                t = elapsed / durationInMs;
                v = interpolator.getInterpolation(t);

                LatLng currentPosition = new LatLng(
                        startPosition.latitude * (1 - t) + nextPosition.latitude * t,
                        startPosition.longitude * (1 - t) + nextPosition.longitude * t);

                mMarker.setPosition(currentPosition);

                // Repeat till progress is complete.
                if (t < 1) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                } else {
                    if (hideMarker) {
                        mMarker.setVisible(false);
                    } else {
                        mMarker.setVisible(true);
                    }
                }
            }
        });

    }




google-maps-mobile