Google Maps API v2中的旋转标记

6
我已经按照这个答案并且成功了。https://dev59.com/S1sV5IYBdhLWcg3w-i-l#37048987 但是我现在面临的问题是:
  1. 当我停在任何位置时,它不稳定。即使我没有移动,我也会得到随机方位值。
  2. 当我转弯时,它是逆时针旋转的,这是错误的。它应该转短弯。
这是我正在使用的代码:
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;
    }

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

                    CameraPosition camPos = CameraPosition
                            .builder(mMap.getCameraPosition())
                            .bearing(bearing)
                            .target(marker.getPosition())
                            .build();
                    mMap.animateCamera(CameraUpdateFactory.newCameraPosition(camPos));

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

onLocationChanged()方法中
float toRotation = (float) bearingBetweenLocations(toLatLng(oldLocation), toLatLng(newLocation));
rotateMarker(my_marker, toRotation);
1个回答

5

最终我找到了答案并在此发布,希望其他人也能从中受益。

每当我的 onLocationChanged 更新时,我会检查我的旧位置和当前位置,然后更新标记。代码如下所示:

 double oldLat = oldLocation.getLatitude();
 double oldLng = oldLocation.getLongitude();

 double newLat = newLocation.getLatitude();
 double newLng = newLocation.getLongitude();

 if (oldLat != newLat && oldLng != newLng){
      updateMyLocation(toLatLng(oldLocation), toLatLng(mCurrentLocation));
 }

我还更新了我的标记旋转代码。这会旋转标记并使用平滑动画移动到新位置。(调整持续时间以获得平滑动画)。

float rotation = (float) SphericalUtil.computeHeading(old, new);
rotateMarker(bus_marker, new, rotation);

private void rotateMarker(final Marker marker, final LatLng destination, final float rotation) {

    if (marker != null) {

        final LatLng startPosition = marker.getPosition();
        final float startRotation = marker.getRotation();

        final LatLngInterpolator latLngInterpolator = new LatLngInterpolator.Spherical();
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.setDuration(3000); // duration 3 second
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

                try {
                    float v = animation.getAnimatedFraction();
                    LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, destination);
                    float bearing = computeRotation(v, startRotation, rotation);

                    marker.setRotation(bearing);
                    marker.setPosition(newPosition);

                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
        valueAnimator.start();
    }
}
private static float computeRotation(float fraction, float start, float end) {
    float normalizeEnd = end - start; // rotate start to 0
    float normalizedEndAbs = (normalizeEnd + 360) % 360;

    float direction = (normalizedEndAbs > 180) ? -1 : 1; // -1 = anticlockwise, 1 = clockwise
    float rotation;
    if (direction > 0) {
        rotation = normalizedEndAbs;
    } else {
        rotation = normalizedEndAbs - 360;
    }

    float result = fraction * rotation + start;
    return (result + 360) % 360;
}

嘿,抱歉挖掘这个旧问题,你介意发布你的LatLngInterpolator代码吗? - Vasili Fedotov
1
@VasiliFedotov 这里是 LatLngInterpolator 的链接 https://gist.github.com/hardikbhalodi/671ab28c81d3392fba45bc72fa549be2 - satti8893
感谢分享这个解决方案,它像魔法一样有效。 - Brahim Belghmi

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