mapbox / mapbox-gl-native

Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL
https://mapbox.com/mobile
Other
4.37k stars 1.33k forks source link

Add example using property animation #4206

Closed tobrun closed 8 years ago

tobrun commented 8 years ago

@cammace created an example of Marker animation using Handler.postDelayed(). While this works, this isn't the ideal implementation. This gave me the idea to use PropertyAnimation from the Android SDK.

Result can be seen here.

The rough code for this is:

LatLng brussels = new LatLng(50.900446, 4.485251);
LatLng washington = new LatLng(38.897108, -77.036716);

final Marker marker = mapboxMap.addMarker(new MarkerOptions().position(brussels));
ValueAnimator markerAnimator = ValueAnimator.ofObject(new TypeEvaluator<LatLng>() {

     @Override
      public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
           return new LatLng(startValue.getLatitude() + (endValue.getLatitude() - startValue.getLatitude()) * fraction, startValue.getLongitude() + (endValue.getLongitude() - startValue.getLongitude()) * fraction);
      }

}, new LatLng[]{brussels, washington});

markerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
                if (marker != null) {
                     marker.setPosition((LatLng) animation.getAnimatedValue());
                }
        }
});

markerAnimator.setDuration(7500);
markerAnimator.setRepeatCount(ValueAnimator.INFINITE);
markerAnimator.setRepeatMode(ValueAnimator.REVERSE);
markerAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
markerAnimator.start();
cammace commented 8 years ago

I created something similar the other day using ObjectAnimator but when testing I was having lagging issues. Here's a snippet:

public static void animateMarker(Marker marker, LatLng finalPosition){
    TypeEvaluator<LatLng> typeEvaluator = new TypeEvaluator<LatLng>() {
        @Override
        public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
            return interpolate(startValue, endValue, fraction);
        }
    };

    Property<Marker, LatLng> property = Property.of(Marker.class, LatLng.class, "position");
    ObjectAnimator objectAnimator = ObjectAnimator.ofObject(marker, property, typeEvaluator, finalPosition);
    objectAnimator.setDuration(5000);
    objectAnimator.start();
}

Replacing it with your code, I get better performance but still some lag occurs, I'll keep tweaking around and see if I can find the cause. On another note, has there been any thought into adding interpolation methods within the MathUtils class? I can think of three different ways to interpolate, spherical, linear, and a sort of fixed linear that will always take the shortest path across the 180th meridian. All require lots of math that would be easier if included within the library.

tobrun commented 8 years ago

@cammace That look great as well. sorry that I missed that!

About the lag, I haven't looked into it but I believe this has to do with the overhead associated with calling JNI methods (JNI is the bridge between java en C++), which with this type of animation are constantly calling. If we want to make this more performant we need to port it to C++.

About the the suggestions for MathUtils, those seem awesome as well!

cammace commented 8 years ago

That makes sense, i'll dig deeper in the code and check it out.