1. 程式人生 > >Android 3D旋轉動畫——Rotate3dAnimation

Android 3D旋轉動畫——Rotate3dAnimation

在Android中如果想要實現3D效果一般有兩種選擇,一是使用Open GL ES,二是使用Camera。Open GL ES使用起來太過複雜,一般是用於比較高階的3D特效或遊戲,像比較簡單的一些3D效果,使用Camera就足夠了。

Camera中提供了三種旋轉方法,分別是rotateX()、rotateY()和rotateZ,呼叫這三個方法,並傳入相應的角度,就可以讓檢視圍繞這三個軸進行旋轉,而今天我們要做的中軸旋轉效果其實就是讓檢視圍繞Y軸進行旋轉。使用Camera讓檢視進行旋轉的示意圖,如下所示:

                                  

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.rotatepicbrowserdemo;

import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.graphics.Camera;
import android.graphics.Matrix;

/**
 * An animation that rotates the view on the Y axis between two specified
 * angles. This animation also adds a translation on the Z axis (depth) to
 * improve the effect.
 */
public class Rotate3dAnimation extends Animation {
    private final float mFromDegrees;
    private final float mToDegrees;
    private final float mCenterX;
    private final float mCenterY;
    private final float mDepthZ;
    private final boolean mReverse;
    private Camera mCamera;

    /**
     * Creates a new 3D rotation on the Y axis. The rotation is defined by its
     * start angle and its end angle. Both angles are in degrees. The rotation
     * is performed around a center point on the 2D space, definied by a pair of
     * X and Y coordinates, called centerX and centerY. When the animation
     * starts, a translation on the Z axis (depth) is performed. The length of
     * the translation can be specified, as well as whether the translation
     * should be reversed in time.
     * 
     * @param fromDegrees
     *            the start angle of the 3D rotation
     * @param toDegrees
     *            the end angle of the 3D rotation
     * @param centerX
     *            the X center of the 3D rotation
     * @param centerY
     *            the Y center of the 3D rotation
     * @param reverse
     *            true if the translation should be reversed, false otherwise
     */
    public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX, float centerY, float depthZ,
            boolean reverse) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;
        mCenterX = centerX;
        mCenterY = centerY;
        mDepthZ = depthZ;
        mReverse = reverse;
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mCamera = new Camera();
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final float fromDegrees = mFromDegrees;
        float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
        final float centerX = mCenterX;
        final float centerY = mCenterY;
        final Camera camera = mCamera;
        final Matrix matrix = t.getMatrix();
        // 將當前的攝像頭位置儲存下來,以便變換進行完成後恢復成原位,
        camera.save();
        // camera.translate,這個方法接受3個引數,分別是x,y,z三個軸的偏移量,我們這裡只將z軸進行了偏移,
        if (mReverse) {
            // z的偏移會越來越大。這就會形成這樣一個效果,view從近到遠
            camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
        } else {
            // z的偏移會越來越小。這就會形成這樣一個效果,我們的View從一個很遠的地方向我們移過來,越來越近,最終移到了我們的視窗上面~
            camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
        }

        // 是給我們的View加上旋轉效果,在移動的過程中,檢視還會移Y軸為中心進行旋轉。
        camera.rotateY(degrees);
        // 是給我們的View加上旋轉效果,在移動的過程中,檢視還會移X軸為中心進行旋轉。
        // camera.rotateX(degrees);

        // 這個是將我們剛才定義的一系列變換應用到變換矩陣上面,呼叫完這句之後,我們就可以將camera的位置恢復了,以便下一次再使用。
        camera.getMatrix(matrix);
        // camera位置恢復
        camera.restore();

        // 以View的中心點為旋轉中心,如果不加這兩句,就是以(0,0)點為旋轉中心
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
    }
}