Подтвердить что ты не робот

Анимация маркеров на Google Maps V2

Каков наилучший способ анимации маркеров на картах Goole с помощью v2 Api?

Я работаю над картографической игрой, где я отслеживаю местоположения людей и показываю их на карте друг для друга. Когда люди двигаются, я хочу анимировать маркер от его текущего до его последней позиции. У каждого человека есть направление, поэтому мне нужно соответствующим образом повернуть маркер.

Каков наилучший способ сделать это с помощью нового API Карт Google?

4b9b3361

Ответ 1

Некоторые инженеры Google предоставили приятное демо-видео с некоторым изящным примером кода о том, как анимация маркеров от начальной точки до конечной точки для всех различных версий Android:

Соответствующий код находится здесь:

https://gist.github.com/broady/6314689

И хорошее демо-видео всего в действии.

http://youtu.be/WKfZsCKSXVQ

OLD DEPRECATED ANSWER BELOW

В документации упоминается, что значки маркера не могут быть изменены:

Пиктограмма

Растровое изображение, отображаемое для маркера. Если значок не отображается, отображается значок по умолчанию. Вы можете указать альтернативную окраску значка по умолчанию, используя defaultMarker (float). Вы не можете изменить значок после создания маркера.

Документация API Google Maps v2

Вам нужно будет отслеживать определенные маркеры, возможно, используя метод, аналогичный описанному здесь: Связать маркер с объектом, затем выяснить который необходимо обновить. Вызовите .remove() на маркере, затем создайте повернутое изображение в зависимости от "направления", которое вы хотите, создайте новый маркер с этим изображением и добавьте новый маркер к карте.

Вам не нужно "очищать" карту, просто удалите маркер, который вы хотите изменить, создайте новый, затем добавьте его обратно на карту.

К сожалению, новый API Карт еще не очень гибкий. Надеюсь, Google продолжает улучшать его.

Ответ 2

Маркер имеет новую функцию, добавленную по версии 7 API v2. Marker.setIcon, поэтому вы можете использовать несколько значков для отображения направления.

Ответ 3

Пример использования для DiscDev ansrwer (выше):

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

И для тех из вас, кто использует GPS/или любой поставщик позиции, который получает обновления местоположения:

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

ВАЖНО:

В пределах 1MarkerAnimation.java Если продолжительность анимации установлена ​​на X, и вы получаете обновления местоположения со скоростью меньше X, запускаются несколько анимаций, и вы можете видеть мерцание маркера.

Чтобы избежать этого, метод animationMarkerToICS (например, я взял здесь animationMarkerToICS), должен выглядеть примерно так:

реализация полного метода:

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.

Ответ 4

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

    }