在 Google Maps V2 Android 上根据用户方向旋转标记

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20704834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:18:47  来源:igfitidea点击:

Rotate marker as per user direction on Google Maps V2 Android

androidgoogle-maps-markersaccelerometermarkerbearing

提问by Scorpion

I want to rotate marker as per bearing or sensor value received from Accelerometer to show the user where actually he is moving. I have set marker icon and flat value to true but its not working as required.

我想根据从加速度计接收到的轴承或传感器值旋转标记,以向用户显示他实际移动的位置。我已将标记图标和平面值设置为 true,但它没有按要求工作。

mCurrentLocationMarker.position(new LatLng(
                            LocationUtils.sLatitude, LocationUtils.sLongitude));
                    mCurrentLocationMarker.icon(icon);
                    mCurrentLocationMarker.flat(true);
                    mCurrentLocationMarker.rotation(LocationUtils.sBearing);

                    if (currentMarker != null) {
                        currentMarker.setPosition(new LatLng(
                                LocationUtils.sLatitude,
                                LocationUtils.sLongitude));
                    } else {
                        currentMarker = mGoogleMap
                                .addMarker(mCurrentLocationMarker);
                    }
                    animateCameraTo(true);

I have used this markeras marker.

我用它标记作为标记。

I don't know why its not rotating as per user's direction. If anyone has any idea please kindly help me where i am making mistake.

我不知道为什么它没有按照用户的方向旋转。如果有人有任何想法,请帮助我哪里出错了。

LocationUtils.sBearing is the value of Bearing which i received from onLocationChanged or accelerometer.

LocationUtils.sBearing 是我从 onLocationChanged 或加速度计收到的 Bearing 值。

Basically I want to make my marker same as google maps marker which shows user in which direction they are moving or turning.

基本上我想让我的标记与谷歌地图标记相同,它向用户显示他们正在移动或转向的方向。

回答by Breavyn

This is an old question and it appears the API has changed since then.

这是一个老问题,从那时起 API 似乎发生了变化。

I'm assuming you are able to get the devices bearing. If not here is a handy tutorial.

我假设你能够得到设备的轴承。如果没有,这里有一个方便的教程

First thing is to create a marker we can use for bearing updates.

首先是创建一个标记,我们可以使用它来进行更新。

private Marker marker;

// Create this marker only once; probably in your onMapReady() method
marker = mGoogleMap.addMarker(new MarkerOptions()
        .position(new LatLng(myLatitude, myLongitude))
        .flat(true));

Note the .flat(true)portion. The ensures our marker is north alignedso that our bearings will work correctly even if the user rotates the map.

注意.flat(true)部分。确保我们的标记与北对齐,这样即使用户旋转地图,我们的方位也能正常工作。

Now when you get your bearing updates you can do the following

现在,当您获得轴承更新时,您可以执行以下操作

marker.setRotation(bearing);
// or if following the linked tutorial
// marker.setRotation((float) azimuth);

This assumes your marker icon has the forward direction at the top. If your marker is rotated like the one pictured, you will have to adjust the bearing to compensate before setting it to the marker. Just a simple setRotation(bearing - 45)should do it.

这假设您的标记图标在顶部具有向前方向。如果您的标记像图中那样旋转,则必须先调整方位以进行补偿,然后再将其设置到标记上。只是一个简单的setRotation(bearing - 45)应该做。

回答by satti8893

Im posting this answer because people like me who are searching for a solution related to the above question might find it useful.

我发布此答案是因为像我这样正在寻找与上述问题相关的解决方案的人可能会发现它很有用。

So here how i did it.

所以在这里我是如何做到的。

As @colin said you must enable .flat(true)to rotate markers.

正如@colin 所说,您必须启用.flat(true)旋转标记。

1.For bearing angle i have used the following code.

1.对于轴承角,我使用了以下代码。

Here latLng1 - my old location && latLng2 - my new location

这里 latLng1 - 我的旧位置 && latLng2 - 我的新位置

private double bearingBetweenLocations(LatLng latLng1,LatLng latLng2) {

        double PI = 3.14159;
        double lat1 = latLng1.latitude * PI / 180;
        double long1 = latLng1.longitude * PI / 180;
        double lat2 = latLng2.latitude * PI / 180;
        double long2 = latLng2.longitude * PI / 180;

        double dLon = (long2 - long1);

        double y = Math.sin(dLon) * Math.cos(lat2);
        double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
                * Math.cos(lat2) * Math.cos(dLon);

        double brng = Math.atan2(y, x);

        brng = Math.toDegrees(brng);
        brng = (brng + 360) % 360;

        return brng;
    }

2.To rotate marker using above bearing angle i have used this code

2.要使用上述方位角旋转标记,我使用了此代码

Here isMarkerRotatingis a boolean value. Add isMarkerRotating = falsein OnCreatemethod

isMarkerRotating是一个布尔值。添加isMarkerRotating = falseOnCreate方法

private void rotateMarker(final Marker marker, final float toRotation) {
        if(!isMarkerRotating) {
            final Handler handler = new Handler();
            final long start = SystemClock.uptimeMillis();
            final float startRotation = marker.getRotation();
            final long duration = 2000;

            final Interpolator interpolator = new LinearInterpolator();

            handler.post(new Runnable() {
                @Override
                public void run() {
                    isMarkerRotating = true;

                    long elapsed = SystemClock.uptimeMillis() - start;
                    float t = interpolator.getInterpolation((float) elapsed / duration);

                    float rot = t * toRotation + (1 - t) * startRotation;

                    float bearing =  -rot > 180 ? rot / 2 : rot;

                    marker.setRotation(bearing);

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

3.using above code

3.使用上面的代码

LatLng oldLocation, newLocaation;

float bearing = (float) bearingBetweenLocations(oldLocation, newLocaation);
rotateMarker(start_marker, bearing);

回答by Shylendra Madda

In Kotlin by using Google SphericalUtil class we can get bearing by passing source and destination LatLngs like:

在 Kotlin 中,通过使用 Google SphericalUtil 类,我们可以通过传递源和目标 LatLngs 来获得方位,例如:

fun calculateBearing(lat1: Double, lng1: Double, lat2: Double, lng2: Double): Float {
        val sourceLatLng = LatLng(lat1, lng1)
        val destinationLatLng = LatLng(lat2, lng2)
        return SphericalUtil.computeHeading(sourceLatLng, destinationLatLng).toFloat()
    }

Then set this result 'bearing` to the marker like

然后将此结果“轴承”设置为标记,例如

Val bearing  = calculateBearing(lat1, lng1, lat2, lng2)
marker.rotation(bearing)

Reference: https://developers.google.com/maps/documentation/android-sdk/utility/#spherical

参考:https: //developers.google.com/maps/documentation/android-sdk/utility/#sphereal