第六章 一張白紙好作畫—Canvas畫布(5),canvas畫布

來源:互聯網
上載者:User

第六章 一張白紙好作畫—Canvas畫布(5),canvas畫布
6.4.8地區 android.graphics.Region與Region.Op

在Canvas的繪畫時,我們可能碰到止需要顯示半個矩形,或者顯示一部分圖片,那麼我們就要用到Canvas的設定地區的方法,有clipRect(Rect rect,Region.Op op)、clipRegion(Region region)這兩個方法。Region表示的是一個地區和Rect不同的是,它可以表示的一個不規則的樣子,可以是橢圓、多邊形等等,當然Region也可以表示一個矩形,而Rect僅僅是矩形。

同樣Region的boolean contains(int x, int y) 成員可以判斷一個點是否在該地區內。

Region.Op是多個地區疊加效果的參數。

public enum Op {

DIFFERENCE(0),//DIFFERENCE 第一個中不同於第二個的部分顯示出來

INTERSECT(1),//INTERSECT 取兩者交集,預設的方式

UNION(2),//UNION 取全集

XOR(3),//XOR 補集,就是全集的減去交集的剩餘部分顯示

REVERSE_DIFFERENCE(4),//第二個不同於第一個的部分顯示

REPLACE(5);//REPLACE 顯示第二個的

}

   

下面我們來解讀下SDK中的ApiDemos(com.example.android.apis.graphics.Region.java)這個樣本。6-4所示。

圖6-4 Region的樣本

 

它主要是將兩個Rect放在同一個Region中,根據不同的Region.Op來製作出的,有顏色的地區為有效區,不同的顏色表示合并後產生的不同Rect。

核心代碼如下:

// 定義兩個Rect(矩形)

mRect1.set(10, 10, 100, 80);

mRect2.set(50, 50, 130, 110);

// 定義一個Region,用來儲存兩個Rect的集合

Region rgn = new Region();

// 將mRect1添加進Region中

rgn.set(mRect1);

// 將mRect2添加進Region中,注意這裡的第二個參數,他就是要傳進去得效果的標示,詳細參見上面的Region.Op說明。

rgn.op(mRect2, op);

// Region的迭代器,可以講一個Region分解成不同的Rect,通過iter.next(Rect r)方法來把每個矩形提取出來。

RegionIterator iter = new RegionIterator(rgn);

Rect r = new Rect ();

while (iter.next(r)) {

canvas.drawRect(r, mPaint);

}

6.4.9千姿百態矩陣變換 android.graphics.Matrix

對前面的基礎知識有所瞭解後,我們就可以來看android.graphics.Matrix類,該類表示一個轉換矩陣,它確定如何將一個座標空間的點映射到另一個座標空間。通過設定Matrix對象的屬性並將其應用於Canvas對象或Bitmap對象,我們可以對該對象執行各種圖形轉換。這些轉換函式包括平移(x和y重新置放)、旋轉、縮放和傾斜,達到很炫的效果。

matrix 對象被視為具有如下內容的 3 x 3 的矩陣:

在傳統的轉換矩陣中,u、v和w屬性具有其它功能。Matrix類只能在二維空間中操作,因此始終假定屬性值u和v為0.0,屬性值w為1.0。換句話說,矩陣的有效值如下:

您可以擷取和設定 Matrix 對象的全部六個其它屬性的值:a、b、c、d、tx 和 ty。

Matrix類支援四種主要的轉換函式類型:平移、縮放、旋轉和傾斜。對於這些函數中的三種,有特定的方法,如表6-8中所述。

方法

矩陣值

顯示結果

說明

Translate(tx,ty)

平移(置換),

將映像向右移動tx像素,向下移動ty 像素。

scale(sx, sy)

縮放,

調整映像的大小,方法是將每個像素的位置在 x 軸方向上乘以sx並在 y 軸方向上乘以sy。

rotate(q)

旋轉,

將映像旋轉一個以弧度為單位的角度q。

Skew(skx, sky)

傾斜,

以平行於X軸或Y軸的方向逐漸滑動映像。skx 值充當乘數,控制沿x 軸滑動的距離;sky控制沿y軸滑動的距離。

表6-8 Matrix類支援的四種主要的轉換函式

 

下面的代碼簡單的實現了圖片的倒影鏡像

Matrix mMatrix = new Matrix();

mMatrix.setScale(1.0f, -1.0f);

canvas.drawBitmap(mBitmap, mMatrix, null);

 

上述的四種操作的方法,每種操作方法都有三種介面setXX、preXX、postXX。setXX將使整個matrix的值為設定的值。preXX是將新的變換矩陣左乘原來的矩陣,而postXX是將新的變換矩陣右乘原來的變換矩陣。

 

經驗分享:

在組合matrix中preTranslate、setTranslate、postTranslate是有很大區別的。抽象的說pre方法是向前“生長”,post方法是向後“生長”,下面還是通過2個例子來說明:

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).

另外可以注意這個方法Matrix.mapRect(RectF rect);對RectF矩形進行變換。

 

矩陣一般應用在變換view的時候,那麼很多時候我們將需要將一些點或矩形,進行轉換,Android的Matrix為我們提供了很方便的方法來進行計算。下面我們來看個例子:

float[] p1 = {1000f,100f};

float[] p2 = {1000f,100f};

 

// 下面是一個正向的過程

// 原始變換矩陣

Matrix m1 = new Matrix();

// m1的逆矩陣

Matrix m2 = new Matrix();

Log.d("test111 ", ""+p1[0]+","+p1[1]);

m1.postTranslate(100, 300);

m1.postScale(0.6f, 0.3f);

m1.postRotate(45.f);

// 這個過程是將p1{1000f,100f}這個點通過了m1的轉換,變成了一個新的點p1,這時候p1已經變成了轉換後的點了。

m1.mapPoints(p1);

Log.d("test222 ", ""+m1.toString());

Log.d("test333 ", ""+p1[0]+","+p1[1]);

 

// 下面是一個逆向的過程

// 將p1經過轉換的點,賦值給p2

p2 = p1;

Log.d("test444 ", ""+p2[0]+","+p2[1]);

// 這裡將m1進行了逆向,然後存放在m2裡

boolean temp = m1.invert(m2);

Log.d("test555 ", ""+m2.toString());

Log.d("test666 ", ""+temp);

// 這裡轉換過的點可以理解為轉換後的點,通過逆向矩陣m2得到最原始的點的位子,並存放在p2裡。

m2.mapPoints(p2);

Log.d("test777 ", ""+p2[0]+","+p2[1]);

 

圖6-5顯示了啟動並執行結果。

圖6-5 矩陣逆向例子的結果

 

經驗分享:

通過上面的例子我們可以看到,你可能在一個時候只需要用到一部分,及矩陣正向的邏輯,或矩陣逆向的邏輯。需要注意的是下面2個方法:

1)m1.mapPoints(p1);//這個過程是將p1{1000f,100f}這個點通過了m1的轉換,變成了一個新的點p1,這時候p1已經變成了轉換後的float數組了。

2)m1.invert(m2);//這裡將m1進行了逆向,然後存放在m2裡

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.