Matrix矩陣變幻
基本變幻
- scal 縮放
- translate平移
- roate旋轉
- concat合併
- skew扭曲
基本介紹
Preconcats matrix相當於右乘矩陣,Postconcats matrix相當於左乘矩陣。倒影就是縮放爲負數
Matrix是一個3*3的矩陣,其值對應如下:
下面給出具體座標對應變形的屬性
|scaleX, skewX, translateX |
|skewY, scaleY, translateY |
|0 , 0 , scale |
常用方法
- setTranslate(float dx,float dy):控制Matrix進行位移。
- setSkew(float kx,float ky):控制Matrix進行傾斜,kx、ky爲X、Y方向上的比例。
- setSkew(float kx,float ky,float px,floatpy):控制Matrix以px、py爲軸心進行傾斜,kx、ky爲X、Y方向上的傾斜比例。
- setRotate(float degrees):控制Matrix進行depress角度的旋轉,軸心爲(0,0)。 setRotate(float
- degrees,float px,float py):控制Matrix進行depress角度的旋轉,軸心爲(px,py)。
- setScale(float sx,float sy):設置Matrix進行縮放,sx、sy爲X、Y方向上的縮放比例。
- setScale(float sx,float sy,float px,floatpy):設置Matrix以(px,py)爲軸心進行縮放,sx、sy爲X、Y方向上的縮放比例。
注意:以上的set方法,均有對應的post和pre方法, Matrix調用一系列set,pre,post方法時,可視爲將這些方法插入到一個隊列. 當然,按照隊列中從頭至尾的順序調用執行.其中pre表示在隊頭插入一個方法, post表示在隊尾插入一個方法.而set表示把當前隊列清空,並且總是位於隊列的最中間位置,當執行了一次set後:pre方法總是插入到set前部的隊列的最前面,post方法總是插入到set後部的隊列的最後面
抽象的說pre方法是向前”生長”, post方法是向後”生長”,具體拿個例子來說,
比如一個matrix調用了下列一系列的方法:
matrix.preScale(0.5f, 1); matrix.preTranslate(10, 0);
matrix.postScale(0.7f, 1); matrix.postTranslate(15, 0);
則座標變換經過的4個變換過程依次是:
translate(10, 0) -> scale(0.5f, 1) -> scale(0.7f,1) -> translate(15, 0)
所以對matrix方法的調用順序是很重要的,不同的順序往往會產生不同的變換效果。 pre方法的調用順序和post方法的互不影響,即以下的方法調用和前者在真實座標變換順序裏是一致的,
matrix.postScale(0.7f, 1);matrix.preScale(0.5f, 1);
matrix.preTranslate(10, 0);matrix.postTranslate(15, 0);
而matrix的set方法則會對先前的pre和post操作進行刷除,而後再設置它的值,比如下列的方法調用:
matrix.preScale(0.5f, 1); matrix.postTranslate(10, 0);
matrix.setScale(1, 0.6f); matrix.postScale(0.7f, 1);
matrix.preTranslate(15, 0);
其座標變換順序是
translate(15, 0) -> scale(1, 0.6f) -> scale(0.7f, 1).
setScale
重新設置了矩陣的值,之前的兩個變換是無效的了,所以最終的顯示效果只有三個變換效果。
Canvas裏scale,translate, rotate, concat方法都是pre方法,如果要進行更多的變換可以先從canvas獲得matrix,變換後再設置回canvas.
示例:
/**
* @author leo
* @date 15-2-26
*
* 練習使用Matrix對Bitmap進行處理
*
*/
class MatrixView extends View{
Matrix matrix;
Paint mPaint;
Bitmap bitmap;
public MatrixView(Context context) {
super(context);
//初始化矩陣
matrix = new Matrix();
//矩陣平移, 使用時候和pre postTranslate效果一樣
// matrix.setRotate(30); matrix.preRotate(30), matrix.postRorate(30);
/**
* 關於下面兩種情況的說明
* 第一種 :
* matrix.setTranslate(100, 100);
* matrix.postScale(2f, 2f);
* 實現這樣的矩陣,post左乘
* [2,0,0] [1,0,100] [2,0,200]
* [0,2,0] × [0,2,100] = [0,2,200]
* [0,0,1] [0,0,1 ] [0,0,1 ]
* 得到的就應該是縮放兩倍後,平移到x=200 y=200的位置
*
* 第二種:
* matrix.setTranslate(100, 100);
* matrix.preScale(2f, 2f);
* 實現這樣的矩陣,pre右乘
* [1,0,100] [2,0,0] [2,0,100]
* [0,1,100] × [0,2,0] [0,2,100]
* [0,0,1 ] [0,0,1] [0,0,1 ]
* 得到的就應該是縮放兩倍後,平移到x=100 y=100的位置
*/
mPaint = new Paint();
Bitmap tmp = BitmapFactory.decodeStream(context.getResources().openRawResource(R.drawable.icon48x48_2));
bitmap = tmp.copy(Config.ARGB_8888, true);
if (tmp != bitmap) {
tmp.recycle();
}
//垂直影像
/*
final float vertical[] = {
1.0F, 0.0F, 0.0F,
0.0F, -1.0F, bitmap.getHeight(),
0.0F, 0.0F, 1.0F};
final float horat[] = {
-1.0F, 0.0F, bitmap.getWidth(),
0.0F, 1.0F, 0.0F,
0.0F, 0.0F, 1.0F};
matrix.setValues(horat);
*/
}
@Override
protected void dispatchDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.dispatchDraw(canvas);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bitmap, matrix, mPaint);
//有陰影的
// canvas.drawBitmap(getReflectedBitmap(bitmap), 0, 0, mPaint);
// mPaint.setColor(Color.RED);
// FontMetrics fm = mPaint.getFontMetrics();
// canvas.drawText("I'm Chinese", 100, 100+(fm.descent - fm.ascent), mPaint);
// matrix.setTranslate(100, 100);
// matrix.postScale(2f, 2f);
// canvas.drawBitmap(bitmap, matrix, mPaint);
// canvas.drawText("I'm Chinese", 200, 200+(fm.descent - fm.ascent), mPaint);
//使用set就是清空矩陣隊列,如果想要繼續上面矩陣變換可以如下:
// Matrix m = new Matrix();
// m.setScale(3.f, 3.f);
// matrix.setConcat(matrix, m);
// canvas.drawBitmap(bitmap, matrix, mPaint);
}
}