Android - Animate Rotation of Map Marker Around X- and Y-axis
Asked Answered
W

0

1

I wonder if it is be possible to animate Google Maps markers rotations along x- and y-axis like how we'd rotate an ImageView using ObjectAnimator around x-axis and/or y-axis. Apparently, one can rotate (change) the orientation of a marker clockwise, which is along z-axis (in X-Y plane), but I seem to be unable to find something similar for even rotating a marker (bitmap) around x- or y-axis. I have found few discussions like this which might be somehow related to what I'm looking for but I am rather confused on how to go about this. Any help is greatly appreciated!

UPDATE I I did further research and came up with a proposal on how to tackle this problem:

  1. Google Map Marker has a setter method for setting its icon, referred to as setIcon. Not only through the MarkerOption but also as an standalone method to reset the Marker icon. This method expects a BitmapDescriptor to be passed in in order to update the icon. Using BitmapDescriptorFactory one can easily get a BitmapDescriptor from a given Bitmap object.

  2. Since Google Maps Marker doesn't support 3D rotations, we need to somehow rotate the Bitmap which goes in place of the Marker icon outside of the Marker itself. One way to do this, as far as my findings go, to create a Canvas and a Camera objects, while former is linked to the Drawable to be 3D rotated, the latter is used to actually perform the 3D rotations.

  3. Using Camera helper methods like rotateX, rotateY, and rotateZ, in addition to any necessary translations, one can obtain a customized Matrix instance. By applying this Matrix to Canvas using, for example, concat or setMatrix method, we enforce the the rotations.

  4. The drawable can be linked to Canvas, that is, we may use Drawable.draw(Canvas canvas) method to actually draw into the Bitmap while 3D transformations are applied. Assuming that the Canvas object is linked to the Bitmap. This way the transformed version of the drawable should now be held by the Bitmap instance.

  5. Using Marker setter method setIcon, we first recycle the older BitmapDescriptor and then create a new one, and pass that object to setIcon.

Questions: I wonder if this is the best way to accomplish what I'm looking for. Moreover, how to actually accomplish an animation. I am certain an approach like the one using Animation and overriding it applyTransformation(float interpolatedTime, Transformation t) won't work as it is only applicable to View objects. I further believe I'm better off using ValueAnimator which provides the necessary timing engine for running animations, that is calculating the animated values and set them on target object, in this case the rotation value.

UPDATE II I have come up with the following snippet which is pretty much self-explanatory. Unfortunately, once the animation starts, the icon is removed and nothing else. I captured the logs to make sure the ValueAnimator actually works and it turns out that it does indeed. I also removed all transformations and made sure the Matrix is identity but that didn't help. Getting the Drawable and attempting to draw that into Bitmap instance via Canvas still doesn't work. In fact, when the animation begins, the icon is simply removed. To verify if bitmap file is really created to be replaced, I tried to sample and save the bitmap into SDCARD as PNG format. It's confirmed that the saved PNGs are all blank and that's why the icon is seen to be removed. Any thought?

    private void animateMarker() {
    if (mCamera == null) {
        mCamera = new Camera();
    }

    ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
    animator.setDuration(300);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
//              float interpolatedTime = ((Float) (animation.getAnimatedValue())).floatValue();
//              final double radians = Math.PI * interpolatedTime;
//              float degrees = (float) (180.0 * radians / Math.PI);
                final Matrix matrix = new Matrix();

//              mCamera.translate(0.0f, 0.0f, (float) (150.0 * Math.sin(radians)));
//              mCamera.rotateX(degrees);
//              mCamera.rotateY(degrees);
//              mCamera.rotateZ(degrees);
//              mCamera.getMatrix(matrix);

                Resources resources = mContext.getResources();
                Drawable drawable = resources.getDrawable(R.drawable.custom_pin);
                Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
                    Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(bitmap);
//              mCamera.applyToCanvas(canvas);
//              canvas.setMatrix(matrix);
//              drawable.draw(canvas);
                canvas.drawBitmap(bitmap, matrix, null);
                mMarkerSetLocation.setIcon(mBitmapDescriptorFactory.fromBitmap(bitmap));
        }
    });
    animator.start();
}
Whyalla answered 13/9, 2015 at 21:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.