轉自 易網通訊
見過沒有用opengl的3D動畫,看了一下,是用的Camera實現的,內部機制實際上還是opengl,不過大大簡化了使用。
Camera就像一個攝像機,一個物體在原地不動,然後我們帶著這個攝像機四處移動,在攝像機裡面呈現出來的畫面,就會有立體感,就可以從各個角度觀看這個物體。
它有旋轉、平移的一系列方法,實際上都是在改變一個Matrix對象,一系列*作完畢之後,我們得到這個Matrix,然後畫我們的物體,就可以了。
常用的API如下:
rotateX(float degree) 繞著x軸旋轉degree個度數
rotateY(float degree) 繞著y軸旋轉degree個度數
rotateZ(float degree) 繞著z軸旋轉degree個度數
translate(float x,float y,float z) 平移一段距離
save()和restore() 作用跟Canvas的一樣,儲存原狀態,*作完之後,恢複到原狀態。
可以touch來拖動圖片以翻轉。這個可以用來做很多事情,比如案頭的立體翻轉、立體相簿等等。
如下:
package chroya.demo.rotate3d;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;
/**
* 圖片三維翻轉
* @author chroya
*/
public class CubeView extends View {
//攝像機
private Camera mCamera;
//翻轉用的圖片
private Bitmap face;
private Matrix mMatrix = new Matrix();
private Paint mPaint = new Paint();
private int mLastMotionX, mLastMotionY;
//圖片的中心點座標
private int centerX, centerY;
//轉動的總距離,跟度數比例1:1
private int deltaX, deltaY;
//圖片寬度高度
private int bWidth, bHeight;
public CubeView(Context context) {
super(context);
setWillNotDraw(false);
mCamera = new Camera();
mPaint.setAntiAlias(true);
face = BitmapFactory.decodeResource(getResources(), R.drawable.x);
bWidth = face.getWidth();
bHeight = face.getHeight();
centerX = bWidth>>1;
centerY = bHeigh>>1;
}
/**
* 轉動
* @param degreeX
* @param degreeY
*/
void rotate(int degreeX, int degreeY) {
deltaX += degreeX;
deltaY += degreeY;
mCamera.save();
mCamera.rotateY(deltaX);
mCamera.rotateX(-deltaY);
mCamera.translate(0, 0, -centerX);
mCamera.getMatrix(mMatrix);
mCamera.restore();
//以圖片的中心點為旋轉中心,如果不加這兩句,就是以(0,0)點為旋轉中心
mMatrix.preTranslate(-centerX, -centerY);
mMatrix.postTranslate(centerX, centerY);
mCamera.save();
postInvalidate();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastMotionX = x;
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
int dx = x - mLastMotionX;
int dy = y - mLastMotionY;
rotate(dx, dy);
mLastMotionX = x;
mLastMotionY = y;
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.drawBitmap(face, mMatrix, mPaint);
}
}