Animate the rotation of the Marker in google map v2

后端 未结 8 1942
感情败类
感情败类 2020-12-16 07:19

i am using google maps v2. i have a marker on map, this marker changes rotation every while. I want to animate the rotation of my maker to rotate smoothly. Can anyone help p

相关标签:
8条回答
  • 2020-12-16 07:26

    With @Bhagaskara Liancer answer.Add var isMarkerRotating with help marker rotate smoothly.

    private boolean isMarkerRotating = false;
    public 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 = 1000;
            float deltaRotation = Math.abs(toRotation - startRotation) % 360;
            final float rotation = (deltaRotation > 180 ? 360 - deltaRotation : deltaRotation) * ((toRotation - startRotation >= 0 && toRotation - startRotation <= 180)
                    || (toRotation - startRotation <=-180 && toRotation- startRotation>= -360) ? 1 : -1);
    
            final LinearInterpolator 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);
                    marker.setRotation((startRotation + t* rotation)%360);
                    if (t < 1.0) {
                        // Post again 16ms later.
                        handler.postDelayed(this, 16);
                    }else {
                        isMarkerRotating = false;
                    }
                }
            });
        }
    
    }
    
    0 讨论(0)
  • 2020-12-16 07:28

    The answer from Alexandr Kolesnik seems to be the most simple. Here's a Kotlin extension version of it.
    You can pass in an interpolator to avoid a little thrash.

    fun Marker.animateRotation(toRotation: Float, interpolator: TimeInterpolator? = AccelerateDecelerateInterpolator()) {
        val animator = ValueAnimator.ofFloat(rotation, toRotation)
        animator.duration = 500
        animator.interpolator = interpolator
        animator.addUpdateListener {
            rotation = it.animatedValue as? Float ?: return@addUpdateListener
        }
    
        animator.start()
    }
    
    0 讨论(0)
  • 2020-12-16 07:29

    That's mine implementation of smooth marker movement with maker image rotation (when it's set to FLAT [important]). The marker is moved to the requested location smoothly plus it's rotated to the requested degree with a proper direction. For example, when moving from 5deg to 355deg it moves anticlockwise, when 355deg to 5deg it moves clockwise.

    public void animateMarker(final Location location)
    {
        if (myMarkerLOC != null) {
            final LatLngInterpolator latLngInterpolator = new LatLngInterpolator.LinearFixed();
            ValueAnimator valueAnimator = new ValueAnimator();
            final LatLng startPosition = myMarkerLOC.getPosition();
            final float startRotation = myMarkerLOC.getRotation();
            final float angle = 180 - Math.abs(Math.abs(startRotation - location.getBearing()) - 180);
            final float right = WhichWayToTurn(startRotation, location.getBearing());
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
            {
                @Override
                public void onAnimationUpdate(ValueAnimator animation)
                {
                    try {
                        if (myMarkerLOC == null) // oops... destroying map during animation...
                        {
                            return;
                        }
                        float v = animation.getAnimatedFraction();
                        LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, PositionUtil.toLatLng(location));
                        float rotation = startRotation + right * v * angle;
                        myMarkerLOC.setRotation((float) rotation);
                        myMarkerLOC.setPosition(newPosition);
                    } catch (Exception ex) {
                        // I don't care atm..
                    }
                }
            });
            valueAnimator.setFloatValues(0, 1);
            valueAnimator.setDuration(300);
            valueAnimator.start();
        }
    }
    private float WhichWayToTurn(float currentDirection, float targetDirection)
    {
        float diff = targetDirection - currentDirection;
        if (Math.abs(diff) == 0)
        {
            return 0;
        }
        if(diff > 180)
        {
            return -1;
        }
        else
        {
            return 1;
        }
    }
    public interface LatLngInterpolator 
    {
        public LatLng interpolate(float fraction, LatLng a, LatLng b);
    
        public class Linear implements LatLngInterpolator 
        {
            @Override
            public LatLng interpolate(float fraction, LatLng a, LatLng b) 
            {
                double lat = (b.latitude - a.latitude) * fraction + a.latitude;
                double lng = (b.longitude - a.longitude) * fraction + a.longitude;
                return new LatLng(lat, lng);
            }
        }
        public class LinearFixed implements LatLngInterpolator 
        {
            @Override
            public LatLng interpolate(float fraction, LatLng a, LatLng b) {
                double lat = (b.latitude - a.latitude) * fraction + a.latitude;
                double lngDelta = b.longitude - a.longitude;
                // Take the shortest path across the 180th meridian.
                if (Math.abs(lngDelta) > 180) {
                    lngDelta -= Math.signum(lngDelta) * 360;
                }
                double lng = lngDelta * fraction + a.longitude;
                return new LatLng(lat, lng);
            }
        }
    }
    

    Missing implementation of "toLatLong" method:

     public static LatLng toLatLng(final Location location)
     {
        return new LatLng(location.getLatitude(), location.getLongitude());
     }
    

    I hope that helps.

    0 讨论(0)
  • 2020-12-16 07:31
    static public void rotateMarker(final Marker marker, final float toRotation, GoogleMap map) {
        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        final float startRotation = marker.getRotation();
        final long duration = 1555;
    
        final Interpolator interpolator = new LinearInterpolator();
    
        handler.post(new Runnable() {
            @Override
            public void run() {
                long elapsed = SystemClock.uptimeMillis() - start;
                float t = interpolator.getInterpolation((float) elapsed / duration);
    
                float rot = t * toRotation + (1 -t) * startRotation;
    
                marker.setRotation(-rot > 180 ? rot/2 : rot);
                if (t < 1.0) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                } 
            }
        });
    }
    

    i have managed to do it :)

    0 讨论(0)
  • 2020-12-16 07:46

    Here is the simple example You can use the following MarkerAnimation class for animating marker with rotation.

    import android.graphics.Point;
    import android.location.Location;
    import android.os.Handler;
    import android.os.SystemClock;
    import android.view.animation.Interpolator;
    import android.view.animation.LinearInterpolator;
    
    import com.gogrocerycart.settings.Constants;
    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.Projection;
    import com.google.android.gms.maps.model.LatLng;
    import com.google.android.gms.maps.model.Marker;
    
    /**
     * Created by Vinil Chandran on 7/6/18.
     */
    
    public class MarkerAnimation {
        private static Location fromPosition;
        private static float angle = 0;
        public static void move(GoogleMap mMap, final Marker marker, final Location toPosition) {
            if (fromPosition != null && marker != null && toPosition != null) {
                final Handler handlerRotation = new Handler();
                final long startAngle = SystemClock.uptimeMillis();
                final float startRotation = marker.getRotation();
                final long durationRotation = 300;
                final Interpolator interpolatorRotation = new LinearInterpolator();
                float bearing = fromPosition.bearingTo(toPosition);
                Print.e("Bearing:" + bearing);
                angle = bearing<0?(360+bearing):bearing;
                angle = angle%360f;
                Print.e("Angle:" + angle);
                handlerRotation.post(new Runnable() {
                    @Override
                    public void run() {
                        long elapsed = SystemClock.uptimeMillis() - startAngle;
                        float t = interpolatorRotation.getInterpolation((float) elapsed / durationRotation);
                        float rot = t * angle + (1 - t) * startRotation;
                        float mAngle = -rot > 180 ? rot / 2 : rot;
                        marker.setRotation(mAngle);
    
                        if (t < 1.0) {
                            handlerRotation.postDelayed(this, 16);
                        } else {
                            final Handler handler = new Handler();
                            final long start = SystemClock.uptimeMillis();
                            Projection projection = mMap.getProjection();
                            Point startPoint = projection.toScreenLocation(marker.getPosition());
                            final LatLng startLatLng = projection.fromScreenLocation(startPoint);
                            final long duration = Constants.LOCATION_REQUEST_INTERVAL;
                            final Interpolator interpolator = new LinearInterpolator();
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    long elapsed = SystemClock.uptimeMillis() - start;
                                    float t = interpolator.getInterpolation((float) elapsed
                                            / duration);
                                    double lng = t * toPosition.getLongitude() + (1 - t)
                                            * startLatLng.longitude;
                                    double lat = t * toPosition.getLatitude() + (1 - t)
                                            * startLatLng.latitude;
                                    marker.setPosition(new LatLng(lat, lng));
                                    if (t < 1.0) {
                                        // Post again 16ms later.
                                        handler.postDelayed(this, 16);
                                    }
                                }
                            });
                        }
                    }
                });
            }
            fromPosition = toPosition;
        }
    }
    

    Just call the following code for moving the marker when the location is changed.

    if (carMarker != null) {
          MarkerAnimation.move(mMap,carMarker, location);
    }
    
    0 讨论(0)
  • 2020-12-16 07:49
    boolean isRotating = false;
    public void rotateMarker(final Marker marker, final float toRotation) {
        if(!isRotating) {
            isRotating = true;
            final Handler handler = new Handler();
            final long start = SystemClock.uptimeMillis();
            final float startRotation = marker.getRotation();
            final long duration = 1000;
            float deltaRotation = Math.abs(toRotation - startRotation) % 360;
            final float rotation = (deltaRotation > 180 ? 360 - deltaRotation : deltaRotation) *
                    ((toRotation - startRotation >= 0 && toRotation - startRotation <= 180) || (toRotation - startRotation <= -180 && toRotation - startRotation >= -360) ? 1 : -1);
    
            final LinearInterpolator interpolator = new LinearInterpolator();
            handler.post(new Runnable() {
                @Override
                public void run() {
                    long elapsed = SystemClock.uptimeMillis() - start;
                    float t = interpolator.getInterpolation((float) elapsed / duration);
                    marker.setRotation((startRotation + t * rotation) % 360);
                    if (t < 1.0) {
                        // Post again 16ms later.
                        handler.postDelayed(this, 16);
                    } else {
                        isRotating = false;
                    }
                }
            });
        }
    }
    

    This is how I rotate the marker, I don't know this is the best code or not. But I think it will prevent wrong rotation. EDIT: Add var isRotating (Thanks @Trần Văn Huy)

    Update Explanation:

    0 讨论(0)
提交回复
热议问题