Как заставить маркер пересекать ломаную линию в Java?

#java #android #google-maps #marker #google-polyline

Вопрос:

Я работаю над приложением, похожим на uber, didi и т. Д. У меня проблема при создании анимации транспортных средств (переход из точки А в точку Б), я нашел этот код в Интернете, и он работает довольно хорошо:

 public void animateMarker(final LatLng startPosition, final LatLng toPosition,final boolean hideMarke) {
        final Handler handler = new Handler();
        final Marker m = map.addMarker(new MarkerOptions()
                .position(startPosition)
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus2))
                .title("Camión"));
        final long start = SystemClock.uptimeMillis();
        Projection proj = map.getProjection();
        Point startPoint = proj.toScreenLocation(m.getPosition());
        final LatLng startLatLng = proj.fromScreenLocation(startPoint);
        final long duration = 5000;

        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;
                m.setPosition(new LatLng(lat, lng));

                if (t < 1.0) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                } else {
                    if (hideMarke) {
                        m.setVisible(false);
                    } else {
                        m.setVisible(true);
                    }
                }
            }
        });
        markers_animations.add(m);
    }
 

У меня есть этот метод, который отвечает за передачу ему позиций списка со всеми координатами, которые мне требуются для полилиний:

 private void controlAnimaciones(List<LatLng> ruta) {
        for (int i=0; i<ruta.size()-1; i  ) {
            if (i<ruta.size()) {
                animateMarker3(ruta.get(i), ruta.get(i 1), true);
            }
        }
    }
 

Он делает то, что я ожидал, если он перемещает маркер из точки A в точку B, но, просто повторяя список, я не знаю, как это объяснить, есть много маркеров, которые перемещаются только от одного элемента списка к следующему, а после этого они останавливаются. Что я хочу сделать, так это добиться того, чтобы один маркер мог перемещаться по всем пунктам списка, я пытался каким-то образом с помощью кода, который я получил из Интернета, попытаться понять его, но у меня не было большого успеха. Как я мог это сделать?

Ответ №1:

В настоящее время в вашем опубликованном коде animateMarker создается маркер для каждого «сегмента» полилинии — он запускает и останавливает движение маркера вдоль одного сегмента, и делает это асинхронно. Это будет иметь эффект маркера, созданного (одновременно) в начале каждого сегмента и анимированного параллельно (почти). Не то, чего ты хочешь.

Итак, вам нужно изменить две вещи:

  1. Создайте маркер один раз в начале первого сегмента.
  2. Продолжайте анимацию второго и последующих сегментов после завершения первого (или предыдущего этапа).

Простой способ сделать это выше-изменить animateMarker , чтобы принять список точек, а не одну точку. Список точек-это ваша полилиния ( ruta ).

Я сделал несколько комментариев, в которых метод был изменен по сравнению с вашим оригиналом.

 public void animateMarker(List<LatLng> pts,final boolean hideMarker) {

   // Simple check to make sure there are enough points in the list.
   if (pts.size() <= 1) {
        // need at least two points.
        return;
    }

    final Handler handler = new Handler();

    // Use first point in list as start.
    final Marker m = mMap.addMarker(new MarkerOptions()
            .position(pts.get(0))
            .title("Camión"));
    Projection proj = mMap.getProjection();
    Point startPoint = proj.toScreenLocation(m.getPosition());
    final LatLng startLatLng = proj.fromScreenLocation(startPoint);
    final long duration = 5000;

    final Interpolator interpolator = new LinearInterpolator();

    handler.post(new Runnable() {
        // start at first segment
        private int segment = 0;
        // initial start time
        long start = SystemClock.uptimeMillis();
        @Override
        public void run() {
            long elapsed = SystemClock.uptimeMillis() - start;
            float t = interpolator.getInterpolation((float) elapsed
                    / duration);
            // Use next point in list as destination
            double lng = t * pts.get(segment 1).longitude   (1 - t)
                    * pts.get(segment).longitude;
            double lat = t * pts.get(segment 1).latitude   (1 - t)
                    * pts.get(segment).latitude;
            m.setPosition(new LatLng(lat, lng));

            if (t < 1.0) {
                // Post again 16ms later.
                handler.postDelayed(this, 16);
            } 

            // check if to move to next segment (or done)
            else if (segment < (pts.size()-2)) {
                // move to next segment
                segment  ;
                start = SystemClock.uptimeMillis();
                handler.postDelayed(this,16);
            } else {
                if (hideMarker) {
                    m.setVisible(false);
                } else {
                    m.setVisible(true);
                }
            }
        }
    });
    markers_animations.add(m);
}
 

И чтобы вызвать анимацию с вашим списком, просто измените свой

 private void controlAnimaciones(List<LatLng> ruta) {
    animateMarker(ruta, true);
}
 

И вот результат.

введите описание изображения здесь

(Обратите внимание, что «скорость» перемещения маркера зависит от длины сегмента. Поскольку продолжительность фиксирована для каждого сегмента, более длинные сегменты заставят маркер двигаться быстрее. Вы можете изменить это на постоянную скорость для любого сегмента, изменив duration ее в зависимости от расстояния между двумя точками.)


Обратите внимание, что приложение animaterMarker поддерживает несколько анимаций естественным образом без изменений. Таким образом, в этом примере карта onMapClickListener вызывает controlAnimaciones каждый щелчок по карте, который выполнялся каждые несколько секунд в демонстрационных целях.

введите описание изображения здесь

Надеюсь, это поможет!

Комментарии:

1. Большое спасибо! это то, что я искал!! Я пытался найти решение сам и сделал это другим и самым сложным способом, но ваш ответ действительно помог мне лучше понять весь код, над которым я работал, и на самом деле он намного красивее, быстрее и читабельнее, чем другое решение, которое я получил! Еще раз спасибо вам!