【问题标题】:How to make a Marker traverse a Polyline in Java?如何使标记在 Java 中遍历折线?
【发布时间】:2021-09-04 01:07:54
【问题描述】:

我正在开发一个应用程序,类似于优步,滴滴等。我在制作车辆动画时遇到问题(从A点到B点),我在互联网上找到了这段代码,它运行良好好吧:

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 点,但是,只是通过迭代列表,我不知道如何解释它,有很多标记只能从列表的一个元素到下一个元素,然后它们停止。我想要做的是实现单个标记可以通过列表的所有点,我一直在尝试以某些方式使用我从互联网上获得的代码,试图理解它,但我没有太多成功。我该怎么做?

【问题讨论】:

    标签: java android google-maps marker google-polyline


    【解决方案1】:

    目前在您发布的代码中,animateMarker 为折线的每个“段”创建一个标记 - 它开始和停止标记沿一个段的移动,并且它异步进行 .这将具有在每个片段的开头(同时)创建标记的效果,并且每个片段都并行(几乎)动画。不是你想要的。

    所以你有两件事要改变:

    1. 在第一段的开头创建一次标记。
    2. 在第一段(或前一段完成)之后继续第二段和后面段的动画。

    执行上述操作的简单方法是修改animateMarker 以接受点列表而不是单个点。点列表是您的折线 (ruta)。

    我制作了一些 cmets,其中的方法是根据您的原始方法修改的。

    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,出于演示目的,每隔几秒执行一次。

    希望这会有所帮助!

    【讨论】:

    • 非常感谢!这就是我要找的!我试图自己获得解决方案,我以一种不同且最复杂的方式做到了,但你的回答确实帮助我更好地理解了我正在处理的所有代码,而且实际上它更漂亮、更快、比我得到的其他解决方案更易读!再次感谢您!
    猜你喜欢
    • 2012-01-19
    • 2019-08-02
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    • 2016-03-08
    • 2022-02-09
    • 1970-01-01
    相关资源
    最近更新 更多