簡體   English   中英

Google Maps v2 上的動畫標記

[英]Animating markers on Google Maps v2

使用 v2 API 在 Google 地圖上為標記設置動畫的最佳方法是什么?

我正在開發一個以地圖為中心的游戲,我可以跟蹤人們的位置並將他們顯示在地圖上供彼此查看。 當人們移動時,我想將一個標記從他當前的位置動畫到他的最新位置。 每個人都有一個方向,所以我需要適當地旋轉標記。

使用新的 Google Maps API 的最佳方法是什么?

一些谷歌工程師提供了一個很好的演示視頻,其中包含一些優雅的示例代碼,關於如何為所有不同版本的 Android 設置從起點到終點的動畫標記:

相關代碼在這里:

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

和一個很好的演示視頻,所有這些都在行動。

http://youtu.be/WKfZsCKSXVQ

下面的舊已棄用答案

在文檔中,提到不能更改標記圖標:

圖標

為標記顯示的位圖。 如果圖標未設置,則顯示默認圖標。 您可以使用 defaultMarker(float) 指定默認圖標的替代顏色。 創建標記后,您將無法更改圖標。

Google Maps API v2 文檔

您將不得不跟蹤特定標記,可能使用類似於此處描述的方法: 將標記鏈接到對象,然后找出需要更新的標記。 在標記上調用.remove() ,然后根據您想要的“方向”創建一個旋轉的圖像,用該圖像創建一個新的標記,並將新的標記添加到地圖中。

您不需要“清除”地圖,只需刪除要修改的標記,創建一個新標記,然后將其添加回地圖即可。

不幸的是,新的 Maps API 還不是很靈活。 希望谷歌繼續改進它。

DiscDev 答案的完整示例(上):

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

享受。

自 API v2 的 rev.7 起,Marker 添加了一個新功能。 Marker.setIcon ,因此您可以使用多個圖標來顯示方向。

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

    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM