40

v2 APIを使用してGoogleマップ上のマーカーをアニメーション化するための最良の方法は何ですか?

私は地図中心のゲームに取り組んでいます。そこでは、人々の位置を追跡し、それらを地図上に表示してお互いに見ることができます。人々が移動するにつれて、私は彼の現在の位置から彼の最新の位置までマーカーをアニメートしたいと思います。人には方向性があるので、マーカーを適切に回転させる必要があります。

新しいGoogleMapsAPIを使用してそれを行うための最良の方法は何ですか?

4

4 に答える 4

71

一部のGoogleエンジニアは、Androidのさまざまなバージョンすべてについて、開始点から終了点までマーカーをアニメーション化する方法に関するエレガントなサンプルコードを含む優れたデモビデオを提供しています。

関連するコードは次のとおりです。

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

そして、そのすべての動作の素晴らしいデモビデオ。

http://youtu.be/WKfZsCKSXVQ

以下の古い非推奨の回答

ドキュメントには、マーカーアイコンは変更できないと記載されています。

アイコン

マーカーに表示されるビットマップ。アイコンを未設定のままにすると、デフォルトのアイコンが表示されます。defaultMarker(float)を使用して、デフォルトアイコンの代替色を指定できます。マーカーを作成した後は、アイコンを変更することはできません。

Google MapsAPIv2のドキュメント

おそらくここで説明されているのと同様の方法を使用して、特定のマーカーを追跡する必要があります。マーカーをオブジェクトにリンクしてから、更新する必要のあるマーカーを特定します。マーカーを呼び出し.remove()てから、必要な「方向」に応じて回転した画像を作成し、その画像を使用して新しいマーカーを作成し、新しいマーカーを地図に追加します。

マップを「クリア」する必要はありません。変更するマーカーを削除し、新しいマーカーを作成してから、マップに追加し直すだけです。

残念ながら、新しいMapsAPIはまだあまり柔軟ではありません。うまくいけば、グーグルはそれを改善し続けます。

于 2013-02-14T20:40:30.813 に答える
10

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

楽しみ。

于 2017-02-05T20:53:19.350 に答える
5

マーカーには、APIv2のrev.7から追加された新しい機能があります。Marker.setIconなので、複数のアイコンを使用して方向を示すことができます。

于 2013-05-21T08:41:07.037 に答える
0
    //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);
                    }
                }
            }
        });

    }
于 2017-12-13T13:27:42.033 に答える