24

Ich möchte einen reibungslosen Übergang zu emulieren Auto Marker auf der Karte zu bewegen.Wie animiert man Marker in Android Map API V2?

Ist es möglich, Marker in Android Map API v2 zu animieren?

+0

Wie ich Sie einheimische Karten-API V2 Verhalten müssen verstehen Marker zum anderes von einer Position zu bewegen, glatt? –

+0

Sie können in diesem Beitrag http://stackoverflow.com/questions/13728041/move-markers-in-google-map-v2-android –

+0

mögliche Duplikate von [Wie animiert Marker, wenn es auf Android-Karte hinzugefügt wird? ] (http://stackoverflow.com/questions/8191582/how-to-animate-marker-when-it-is-added-to-map-on-android) – bummi

Antwort

24

Probieren Sie den folgenden Code aus, um den Marker auf Google Map V2 zu animieren. Sie müssen die Interpolator Klasse verwenden, um die Animation auf dem Marker und behandeln es in dem Handler für die Animation, wie unten anzuwenden:

public void animateMarker(final Marker marker, final LatLng toPosition, 
     final boolean hideMarker) { 
    final Handler handler = new Handler(); 
    final long start = SystemClock.uptimeMillis(); 
    Projection proj = mGoogleMapObject.getProjection(); 
    Point startPoint = proj.toScreenLocation(marker.getPosition()); 
    final LatLng startLatLng = proj.fromScreenLocation(startPoint); 
    final long duration = 500; 
    final Interpolator interpolator = new LinearInterpolator(); 
    handler.post(new Runnable() { 
     @Override 
     public void run() { 
      long elapsed = SystemClock.uptimeMillis() - start; 
      float t = interpolator.getInterpolation((float) elapsed 
        /duration); 
      double lng = t * toPosition.longitude + (1 - t) 
        * startLatLng.longitude; 
      double lat = t * toPosition.latitude + (1 - t) 
        * startLatLng.latitude; 
      marker.setPosition(new LatLng(lat, lng)); 
      if (t < 1.0) { 
       // Post again 16ms later. 
       handler.postDelayed(this, 16); 
      } else { 
       if (hideMarker) { 
        marker.setVisible(false); 
       } else { 
        marker.setVisible(true); 
       } 
      } 
     } 
    }); 
} 
+0

Vielen Dank. Das war sehr hilfreich. – Anil

+0

Wie genau implementieren Sie diesen Code? @Anil? Können Sie den Marker entlang der GPS-Koordinaten bewegen? Bitte posten Sie die Antwort. – momokjaaaaa

+2

Hey, vielen Dank. Es klappt. Der Marker bewegt sich jedoch vor der Startmarkeranimation hin und her. Können Sie mir bitte sagen, wie ich es beheben kann? – Sadia

4

nur eine Version implementiert, versuchen Sie diese

public class MarkerAnimation { 
static GoogleMap map; 
ArrayList<LatLng> _trips = new ArrayList<>() ; 
Marker _marker; 
LatLngInterpolator _latLngInterpolator = new LatLngInterpolator.Spherical(); 

public void animateLine(ArrayList<LatLng> Trips,GoogleMap map,Marker marker,Context current){ 
    _trips.addAll(Trips); 
    _marker = marker; 

animateMarker(); 
} 

    public void animateMarker() { 
     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"); 

     ObjectAnimator animator = ObjectAnimator.ofObject(_marker, property, typeEvaluator, _trips.get(0)); 

     //ObjectAnimator animator = ObjectAnimator.o(view, "alpha", 0.0f); 
     animator.addListener(new Animator.AnimatorListener() { 
      @Override 
      public void onAnimationCancel(Animator animation) { 
       // animDrawable.stop(); 
      } 

      @Override 
      public void onAnimationRepeat(Animator animation) { 
       // animDrawable.stop(); 
      } 

      @Override 
      public void onAnimationStart(Animator animation) { 
       // animDrawable.stop(); 
      } 

      @Override 
      public void onAnimationEnd(Animator animation) { 
       // animDrawable.stop(); 
       if (_trips.size() > 1) { 
        _trips.remove(0); 
        animateMarker(); 
       } 
      } 
     }); 

     animator.setDuration(300); 
     animator.start(); 
    } 

Die Klasse LatLngInterpolator wird von Google-Jungs geschrieben, die Sie wie folgt verwenden können:

public interface LatLngInterpolator { 

public LatLng interpolate(float fraction, LatLng a, LatLng b); 

public class Spherical implements LatLngInterpolator { 
    @Override 
    public LatLng interpolate(float fraction, LatLng from, LatLng to) { 
     // http://en.wikipedia.org/wiki/Slerp 
     double fromLat = toRadians(from.latitude); 
     double fromLng = toRadians(from.longitude); 
     double toLat = toRadians(to.latitude); 
     double toLng = toRadians(to.longitude); 
     double cosFromLat = cos(fromLat); 
     double cosToLat = cos(toLat); 

     // Computes Spherical interpolation coefficients. 
     double angle = computeAngleBetween(fromLat, fromLng, toLat, toLng); 
     double sinAngle = sin(angle); 
     if (sinAngle < 1E-6) { 
      return from; 
     } 
     double a = sin((1 - fraction) * angle)/sinAngle; 
     double b = sin(fraction * angle)/sinAngle; 

     // Converts from polar to vector and interpolate. 
     double x = a * cosFromLat * cos(fromLng) + b * cosToLat * cos(toLng); 
     double y = a * cosFromLat * sin(fromLng) + b * cosToLat * sin(toLng); 
     double z = a * sin(fromLat) + b * sin(toLat); 

     // Converts interpolated vector back to polar. 
     double lat = atan2(z, sqrt(x * x + y * y)); 
     double lng = atan2(y, x); 
     return new LatLng(toDegrees(lat), toDegrees(lng)); 
    } 

    private double computeAngleBetween(double fromLat, double fromLng, double toLat, double toLng) { 
     // Haversine's formula 
     double dLat = fromLat - toLat; 
     double dLng = fromLng - toLng; 
     return 2 * asin(sqrt(pow(sin(dLat/2), 2) + 
       cos(fromLat) * cos(toLat) * pow(sin(dLng/2), 2))); 
    } 
} 
} 

Dann ein Objekt der MarkerAnimation Klasse instanziiert und das Verfahren wie folgt aufrufen:

MarkerAnimation.animateLine(TripPoints,map,MovingMarker,context); 
17

Keine Versionen für mich zur Verfügung gestellt gearbeitet, so habe ich meine individuelle Lösung realisiert. Es bietet sowohl - Standort- und Rotationsanimation.

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

Rotationsberechnung für den angegebenen Anteil der Animation. Marker wird in Richtung gedreht, die zu Ende Drehung näher von Anfang ist:

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; 
} 

Und schließlich Googles LatLngInterpolator:

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); 
     } 
    } 
} 
+0

Ich versuche dies zu implementieren, wie füge ich die Peilung zum Ziel? Haben Sie eine Quelle auf Github des endgültigen Projekts? –

+0

@FrankOdoom Sie sollten Peilung über 'setBearing (float)' oder 'bearingTo (Location)' Methode am übergebenen 'Location destination' Parameter richtig setzen. – skywall

+0

Dies ist die beste Antwort, die ich gefunden habe. Es gibt überhaupt kein Flackern. –

Verwandte Themen