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

Posted

技术标签:

【中文标题】根据 Google Maps V2 Android 上的用户方向旋转标记【英文标题】:Rotate marker as per user direction on Google Maps V2 Android 【发布时间】:2014-01-09 09:17:41 【问题描述】:

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

我用这个 作为标记。

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

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

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

【问题讨论】:

嘘!对此有任何答案或***.com/questions/33687236/… ????? 【参考方案1】:

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

我假设您能够获得设备轴承。如果不是这里是handy tutorial。

首先是创建一个我们可以用于轴承更新的标记。

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) 即可。

【讨论】:

if (mLastLocation.hasBearing()) marker.setRotation(bearing); 对吗? @Stella 如果你是从那里得到你的方向,当然 @Stella 汽车标记正向正确方向移动,但标记/图像感觉其向后/反向移动如何解决?【参考方案2】:

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

所以我是怎么做到的。

正如@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 如果oldnew 位置有点远,这可能不起作用。例如,如果您在 30 秒内更新地图并且车速为 90 英里/小时,那么旧位置和新位置之间的差异将为 0.75 英里,如果它是一条曲线,则它不会给出完美的方向。 @satti8893 bearingBetweenLocations() 返回 0.0【参考方案3】:

在 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()
    

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

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

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

【讨论】:

以上是关于根据 Google Maps V2 Android 上的用户方向旋转标记的主要内容,如果未能解决你的问题,请参考以下文章

如何设置 Android Google Maps API v2 地图以显示全球地图?

Android studio v0.3.2, gradle, google maps v2.0 找不到类“com.google.android.gms.maps.MapFragment

java Android Google Maps V2 - XML中的MapView

Google Maps Android API V2 检查 Google Maps 应用程序是不是被禁用

android google maps v2 在服务中

Google Maps Android v2 中的集群标记