在Google Maps V2 Android中,根据用户方向旋转标记。

23

我希望根据从加速度计接收到的方位或传感器值旋转标记,以向用户显示他实际上正在移动的位置。我已将标记图标和平坦值设置为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);

我使用这个marker作为标记。

我不知道为什么它不会根据用户的方向旋转。如果有人有任何想法,请帮助我找出我的错误所在。

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

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


有没有对这个问题的答案或者 https://stackoverflow.com/questions/33687236/rotate-marker-as-per-user-direction-on-google-maps-v2-android 的解决方案? - Stella
3个回答

23

这是一个老问题,看起来自那时起API已经发生了变化。

我假设您能够获得设备的方位角。如果不能,这里有一个经验丰富的教程

首先要创建一个我们可以用于方向更新的标记。

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

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

现在当您收到方向更新时,可以执行以下操作:

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

假设您的标记图标的前方方向在顶部。如果您的标记像所示旋转了,您将不得不调整方位以进行补偿,然后再将其设置为标记。只需要简单的setRotation(bearing - 45)即可。


如果(mLastLocation.hasBearing()){marker.setRotation(bearing); }对吧? - Stella
@Stella 如果那是你获取方向的地方,当然可以。 - Breavyn
@Stella汽车标记正在向右移动,但标记/图像感觉它正在向后/反向移动,如何解决? - Girish

11

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

以下是我是如何做到的。

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

1.对于方位角,我使用了以下代码。

这里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.要使用上面的方位角旋转标记,我使用了以下代码

这里isMarkerRotating是一个布尔值。在OnCreate方法中添加isMarkerRotating = false

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.使用以上代码

LatLng oldLocation, newLocaation;

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

如何使用您的答案旋转卡车?我尝试了这个解决方案,但是卡车的图像翻转了。@satti8893 - urvi joshi
如果“旧”和“新”位置相距较远,则这可能不起作用。例如,如果您每30秒更新一次地图,汽车速度为90英里/小时,则旧位置和新位置之间的差异将为0.75英里,如果是曲线,则不会给出完美的方向。 - Code Lover
@satti8893 的 bearingBetweenLocations() 方法返回 0.0。 - Girish

4
在 Kotlin 中,通过使用 Google 的 SphericalUtil 类,我们可以通过传递源和目标 LatLng 值来获取方位角,例如:
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()
    }

然后将这个结果“bearing”设置到标记上,如下:

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接