24

Tôi muốn thực hiện chuyển đổi suôn sẻ để mô phỏng điểm đánh dấu xe di chuyển trên bản đồ.Làm thế nào để tạo hiệu ứng đánh dấu trong bản đồ android api V2?

Có thể đánh dấu animate trong bản đồ android api v2 không?

+0

Như tôi hiểu bạn cần hành vi bản đồ API V2 mẹ đẻ để di chuyển điểm đánh dấu từ một vị trí khác thông suốt? –

+0

bạn có thể xem bài đăng này http://stackoverflow.com/questions/13728041/move-markers-in-google-map-v2-android –

+0

bản sao có thể có của [Làm cách nào để tạo dấu đánh dấu khi được thêm vào bản đồ trên Android? ] (http://stackoverflow.com/questions/8191582/how-to-animate-marker-when-it-is-added-to-map-on-android) – bummi

Trả lời

24

Hãy thử mã bên dưới để tạo hoạt ảnh cho điểm đánh dấu trên Google Map V2. Bạn cần phải sử dụng lớp Interpolator để áp dụng các hình ảnh động trên Marker và xử lý nó trong Handler cho hình ảnh động như sau:

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

Cảm ơn rất nhiều. Điều đó cực kỳ hữu ích. – Anil

+0

Bạn triển khai chính xác mã này như thế nào? @Anil? bạn có thể lấy điểm đánh dấu di chuyển dọc theo tọa độ gps không? Vui lòng đăng câu trả lời. – momokjaaaaa

+2

Xin chào, cảm ơn rất nhiều. Nó hoạt động. Nhưng điểm đánh dấu di chuyển qua lại trước khi bắt đầu hoạt ảnh đánh dấu. Bạn có thể vui lòng cho tôi biết cách khắc phục nó không. – Sadia

4

Chỉ cần thực hiện một phiên bản, hãy thử này

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

Lớp LatLngInterpolator được viết sẵn bởi những người Google mà bạn có thể sử dụng như sau:

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

Sau đó tạo một đối tượng của lớp MarkerAnimation và gọi phương thức như thế này:

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

Không ai trong số các phiên bản được cung cấp làm việc cho tôi, vì vậy tôi đã thực hiện giải pháp tùy chỉnh của tôi. Nó cung cấp cả vị trí và hoạt ảnh xoay.

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

Tính toán quay cho phần hoạt ảnh được chỉ định. Marker được xoay theo hướng mà là chặt chẽ hơn từ đầu đến cuối xoay:

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

Và cuối cùng của Google 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

Tôi đang cố gắng để thực hiện điều này làm thế nào để tôi thêm mang đến đích ?, Bạn có bất kỳ nguồn trên github của dự án cuối cùng? –

+0

@FrankOdoom Bạn nên đặt vòng bi theo phương thức 'setBearing (float)' hoặc 'bearingTo (Location)' vào thông số 'Location destination'. – skywall

+0

Đây là câu trả lời hay nhất tôi tìm thấy. Không có nhấp nháy nào cả. –

Các vấn đề liên quan